Orb/python/orb/linkinserter.py
changeset 2 932c358ece3e
equal deleted inserted replaced
1:82f11024044a 2:932c358ece3e
       
     1 # Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved.
       
     2 # This component and the accompanying materials are made available under the terms of the License 
       
     3 # "Eclipse Public License v1.0" which accompanies this distribution, 
       
     4 # and is available at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     5 #
       
     6 # Initial Contributors:
       
     7 # Nokia Corporation - initial contribution.
       
     8 #
       
     9 # Contributors:
       
    10 #
       
    11 # Description:
       
    12 #
       
    13 import unittest
       
    14 import sys
       
    15 from cStringIO import StringIO
       
    16 from optparse import OptionParser
       
    17 from xml.etree import ElementTree as etree
       
    18 import os.path
       
    19 import logging
       
    20 import shutil
       
    21 from guidiser import Guidiser
       
    22 
       
    23 __version__ = "0.1"
       
    24 
       
    25 
       
    26 class LinkFile(object):
       
    27     """
       
    28     Parses string representations of cxxapiref XML files and returns an updated
       
    29     string representation with inserted ids for linking to cxxFunctions.
       
    30     """
       
    31     
       
    32     def __init__(self, guidise=False):
       
    33         self.guidiser = Guidiser()
       
    34         self.guidise = guidise
       
    35     def _get_cxxfunction_elems(self, elem):
       
    36         """
       
    37         Takes an elements and generates a list of all child elements that are called cxxFunction 
       
    38         """
       
    39         return [e for e in elem.getiterator() if e.tag == "cxxFunction"]
       
    40     
       
    41     def _get_funcs_with_no_params(self, func_elem_list):
       
    42         """
       
    43         Takes a list of cxxFunction elements and returns a list of those with no parameters.
       
    44         """
       
    45         no_params = []
       
    46         for func in func_elem_list:
       
    47             apiname = func.find("apiName").text
       
    48             params_elem = func.find("cxxFunctionDetail/cxxFunctionDefinition/cxxFunctionParameters")
       
    49             # if cxxFunctionParameters has no children
       
    50             if len(params_elem.getiterator()) == 1:
       
    51                 no_params.append(apiname)            
       
    52         return no_params
       
    53     
       
    54     
       
    55     def _filter_funcs_with_no_params(self, func_elem_list):
       
    56         """
       
    57         Takes a list of cxxFunction elements and returns a list with parameterless functions
       
    58         and all of their overloads removed.
       
    59         """
       
    60         no_param_funcs = self._get_funcs_with_no_params(func_elem_list)
       
    61         return [func_elem for func_elem in func_elem_list if not func_elem.find("apiName").text in no_param_funcs]
       
    62     
       
    63     def _filter_duplicate_funcs(self, func_elem_list):
       
    64         """
       
    65         Takes a list of cxxFunction elements and returns a list ones with unique apiName text.
       
    66         In the case of overloads the first instance found is taken and the rest are filtered.
       
    67         """
       
    68         seen_func_names = []
       
    69         filtered = []
       
    70         for func_elem in func_elem_list:
       
    71             this_apiname = func_elem.find("apiName").text
       
    72             if not this_apiname in seen_func_names:
       
    73                 filtered.append(func_elem)
       
    74                 seen_func_names.append(this_apiname)
       
    75         return filtered
       
    76     
       
    77     def _insert_id_into_cxxfunction_apiname(self, func_elem):
       
    78         """
       
    79         Takes a cxxFunction element. Returns the element with an id inserted into the child apiName element.
       
    80         """
       
    81         function_scoped_name=func_elem.find("cxxFunctionDetail/cxxFunctionDefinition/cxxFunctionScopedName").text
       
    82         
       
    83         if function_scoped_name == None:
       
    84             function_scoped_name = ""
       
    85         else:
       
    86             function_scoped_name+="::"
       
    87         
       
    88         apiname_id = "".join([function_scoped_name,func_elem.find("apiName").text,"()"])
       
    89        
       
    90         if self.guidise:
       
    91             apiname_id = self.guidiser._get_guid(apiname_id)
       
    92 
       
    93         func_elem.find("apiName").attrib["id"] = apiname_id
       
    94         return func_elem
       
    95         
       
    96     def get_func_elems_to_linkify(self, root):
       
    97         cxxfunction_elems = self._get_cxxfunction_elems(root)
       
    98         cxxfunction_elems = self._filter_funcs_with_no_params(cxxfunction_elems)
       
    99         cxxfunction_elems = self._filter_duplicate_funcs(cxxfunction_elems)
       
   100         return cxxfunction_elems
       
   101     
       
   102     def get_linkified(self, file_as_string):
       
   103         """
       
   104         Takes a string representation of a cxxapiref file and returns the string
       
   105         with inserted cxxFunction ids for any functions that fit the insertion rule.
       
   106         
       
   107         The id insertion rule is:
       
   108         
       
   109         If a function and none of its overloads have no arguments then insert an
       
   110         id that represents a function with no arguments over the first function definition encountered.
       
   111         The id is inserted into the apiName child element of the function.
       
   112         """
       
   113         try:
       
   114             root = etree.fromstring(file_as_string)
       
   115         except Exception, e:
       
   116             raise Exception("Failed to parse string as xml file error was %s" % e)
       
   117         funcs_to_linkify = self.get_func_elems_to_linkify(root)
       
   118         for index in xrange(0, len(funcs_to_linkify)):
       
   119             func = self._insert_id_into_cxxfunction_apiname(funcs_to_linkify[index])
       
   120         return etree.tostring(root)
       
   121         
       
   122 
       
   123 class LinkInserter(object):
       
   124     
       
   125     def __init__(self, link_file):
       
   126         self.link_file = link_file
       
   127         
       
   128     def _handle_xml_file(self, xml_file):
       
   129         """
       
   130         Runs linkify function on each file and writes the result to disk
       
   131         """
       
   132         logging.info("Inserting links into %s" % xml_file)
       
   133         content = open(xml_file, "r").read()
       
   134         try:
       
   135             linkified_contents = self.link_file.get_linkified(content)
       
   136         except Exception,e:
       
   137             logging.error("%s %s" %(e, xml_file))
       
   138             return
       
   139 
       
   140         try:
       
   141             f = open(xml_file, "w")
       
   142         except Exception, e:
       
   143             raise IOError("Could not open xml file %s for writing, error was: %s" % (xml_file, e))
       
   144         else:
       
   145             f.write(linkified_contents)
       
   146             f.close()
       
   147         
       
   148     def _handle_xml_files(self, xml_files):
       
   149         """
       
   150         Iterates over a list of files and calls _handle_xml_file on them
       
   151         """
       
   152         for xml_file in xml_files:
       
   153             self._handle_xml_file(xml_file)
       
   154             
       
   155     def _do_linkifying(self, dir):
       
   156         """
       
   157         Takes a directory and calls a handler function on a list of xml files in that and sub directories.
       
   158         """
       
   159         for root, dirs, files in os.walk(dir):
       
   160             xml_file_paths = [os.path.join(root, f) for f in os.listdir(root) if os.path.splitext(f)[1].lower() == (".xml")]
       
   161             self._handle_xml_files(xml_file_paths)
       
   162             
       
   163     def linkify_dir(self, dir):
       
   164         if not os.path.exists(os.path.abspath(dir)):
       
   165             raise IOError("Directory to linkify does not exist: %s" % dir) 
       
   166         self._do_linkifying(dir)
       
   167         
       
   168 
       
   169 def insertlinks(xml_dir):
       
   170     link_inserter = LinkInserter(LinkFile(guidise=True))
       
   171     link_inserter.linkify_dir(xml_dir)
       
   172 
       
   173 
       
   174 def main():
       
   175     usage = "usage: %prog <Path to the XML content>"
       
   176     parser = OptionParser(usage, version='%prog ' + __version__)
       
   177     (options, args) = parser.parse_args()
       
   178     if len(args) < 1:
       
   179         parser.print_help()
       
   180         parser.error("Please supply the path to the XML content")
       
   181     insertlinks(args[0])
       
   182 
       
   183 
       
   184 if __name__ == '__main__':
       
   185     sys.exit(main())
       
   186 
       
   187     
       
   188 ######################################
       
   189 # Test code
       
   190 ######################################
       
   191 
       
   192 class TestLinkFile(unittest.TestCase):
       
   193 
       
   194     def setUp(self):
       
   195         self.link_file = LinkFile()
       
   196         
       
   197     def test__get_funcs_with_no_params(self):
       
   198         func = """    
       
   199         <cxxClass><cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   200         <apiName>Init0</apiName>
       
   201         <cxxFunctionDetail>
       
   202             <cxxFunctionDefinition>
       
   203                 <cxxFunctionParameters/>
       
   204             </cxxFunctionDefinition>
       
   205         </cxxFunctionDetail>
       
   206     </cxxFunction></cxxClass>
       
   207 """
       
   208         root = etree.fromstring(func)
       
   209         func_list = [e for e in root.getiterator() if e.tag == "cxxFunction"]
       
   210         expected = ["Init0"]
       
   211         returned = self.link_file._get_funcs_with_no_params(func_list)
       
   212         self.assertEqual(expected, returned)
       
   213         
       
   214     def test__get_funcs_with_no_params_ignores_a_func_with_params(self):
       
   215         func = """    
       
   216         <cxxClass><cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   217         <apiName>Init0</apiName>
       
   218         <cxxFunctionDetail>
       
   219             <cxxFunctionDefinition>
       
   220                 <cxxFunctionParameters>
       
   221                     <cxxFunctionParameter>
       
   222                     <cxxFunctionParameterDeclaredType>
       
   223                         <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   224                         </cxxFunctionParameterDeclaredType>
       
   225                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   226                         <apiDefNote/>
       
   227                     </cxxFunctionParameter>
       
   228                 </cxxFunctionParameters>
       
   229             </cxxFunctionDefinition>
       
   230         </cxxFunctionDetail>
       
   231     </cxxFunction></cxxClass>
       
   232 """
       
   233         root = etree.fromstring(func)
       
   234         func_list = [e for e in root.getiterator() if e.tag == "cxxFunction"]
       
   235         expected = []
       
   236         returned = self.link_file._get_funcs_with_no_params(func_list)
       
   237         self.assertEqual(expected, returned)    
       
   238     
       
   239     def test_filter_duplicate_funcs_ignores_duplicate_funcs(self):
       
   240         func = """    
       
   241         <cxxClass>
       
   242             <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   243                 <apiName>Init0</apiName>
       
   244             </cxxFunction>
       
   245             <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   246                 <apiName>Init0</apiName>
       
   247             </cxxFunction>
       
   248         </cxxClass>
       
   249 """     
       
   250         root = etree.fromstring(func)   
       
   251         func_list = [e for e in root.getiterator() if e.tag == "cxxFunction"]
       
   252         expected = [func_list[0]]
       
   253         returned = self.link_file._filter_duplicate_funcs(func_list)
       
   254         self.assertEqual(expected, returned)  
       
   255         
       
   256     def test__filter_funcs_with_no_params_filters_funcs_with_no_params(self):
       
   257         func = """    
       
   258         <cxxClass>
       
   259             <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   260                 <apiName>Init0</apiName>
       
   261                 <cxxFunctionDetail>
       
   262                     <cxxFunctionDefinition>
       
   263                         <cxxFunctionParameters/>
       
   264                     </cxxFunctionDefinition>
       
   265                 </cxxFunctionDetail>
       
   266             </cxxFunction>
       
   267             <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   268                 <apiName>Init1</apiName>
       
   269                 <cxxFunctionDetail>
       
   270                     <cxxFunctionDefinition>
       
   271                         <cxxFunctionParameters>
       
   272                             <cxxFunctionParameter>
       
   273                                 <cxxFunctionParameterDeclaredType>
       
   274                                     <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   275                                 </cxxFunctionParameterDeclaredType>
       
   276                                 <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   277                                 <apiDefNote/>
       
   278                             </cxxFunctionParameter>
       
   279                         </cxxFunctionParameters>
       
   280                     </cxxFunctionDefinition>
       
   281                 </cxxFunctionDetail>
       
   282             </cxxFunction>
       
   283         </cxxClass>
       
   284 """     
       
   285         root = etree.fromstring(func)   
       
   286         func_list = [e for e in root.getiterator() if e.tag == "cxxFunction"]
       
   287         expected = [func_list[1]]
       
   288         returned = self.link_file._filter_funcs_with_no_params(func_list)
       
   289         self.assertEqual(expected, returned)
       
   290         
       
   291     def test__insert_id_into_cxxfunction_apiname(self):
       
   292         func_str = """<cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   293         <apiName>Init0</apiName>
       
   294         <shortdesc/>
       
   295         <cxxFunctionDetail>
       
   296             <cxxFunctionDefinition>
       
   297                 <cxxFunctionAccessSpecifier value="public"/>
       
   298                 <cxxFunctionStorageClassSpecifierStatic/>
       
   299                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   300                 <cxxFunctionScopedName>BTrace</cxxFunctionScopedName>
       
   301                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   302                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   303                 <cxxFunctionParameters>
       
   304                     <cxxFunctionParameter>
       
   305                         <cxxFunctionParameterDeclaredType>
       
   306                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   307                         </cxxFunctionParameterDeclaredType>
       
   308                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   309                         <apiDefNote/>
       
   310                     </cxxFunctionParameter>
       
   311                 </cxxFunctionParameters>
       
   312                 <cxxFunctionAPIItemLocation>
       
   313                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   314                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   315                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   316                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   317                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   318                 </cxxFunctionAPIItemLocation>
       
   319             </cxxFunctionDefinition>
       
   320             <apiDesc/>
       
   321         </cxxFunctionDetail>
       
   322     </cxxFunction>"""
       
   323         func_elem = etree.fromstring(func_str)
       
   324         returned = self.link_file._insert_id_into_cxxfunction_apiname(func_elem)
       
   325         self.assertEquals(returned.find("apiName").attrib["id"], "BTrace::Init0()")
       
   326 
       
   327     def test__insert_id_into_cxxfunction_apiname_when_the_cxxfunction_has_no_scoped_name(self):
       
   328         func_str = """<cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   329         <apiName>Init0</apiName>
       
   330         <shortdesc/>
       
   331         <cxxFunctionDetail>
       
   332             <cxxFunctionDefinition>
       
   333                 <cxxFunctionAccessSpecifier value="public"/>
       
   334                 <cxxFunctionStorageClassSpecifierStatic/>
       
   335                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   336                 <cxxFunctionScopedName/>
       
   337                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   338                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   339                 <cxxFunctionParameters>
       
   340                     <cxxFunctionParameter>
       
   341                         <cxxFunctionParameterDeclaredType>
       
   342                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   343                         </cxxFunctionParameterDeclaredType>
       
   344                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   345                         <apiDefNote/>
       
   346                     </cxxFunctionParameter>
       
   347                 </cxxFunctionParameters>
       
   348                 <cxxFunctionAPIItemLocation>
       
   349                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   350                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   351                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   352                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   353                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   354                 </cxxFunctionAPIItemLocation>
       
   355             </cxxFunctionDefinition>
       
   356             <apiDesc/>
       
   357         </cxxFunctionDetail>
       
   358     </cxxFunction>"""
       
   359         func_elem = etree.fromstring(func_str)
       
   360         returned = self.link_file._insert_id_into_cxxfunction_apiname(func_elem)
       
   361         self.assertEquals(returned.find("apiName").attrib["id"], "Init0()")
       
   362         
       
   363     def test_i_can_insert_an_id_to_a_cxxfunction_apiname(self):
       
   364         file_as_string = """    
       
   365         <cxxClass>
       
   366 <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   367         <apiName>Init0</apiName>
       
   368         <shortdesc/>
       
   369         <cxxFunctionDetail>
       
   370             <cxxFunctionDefinition>
       
   371                 <cxxFunctionAccessSpecifier value="public"/>
       
   372                 <cxxFunctionStorageClassSpecifierStatic/>
       
   373                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   374                 <cxxFunctionScopedName>BTrace</cxxFunctionScopedName>
       
   375                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   376                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   377                 <cxxFunctionParameters>
       
   378                     <cxxFunctionParameter>
       
   379                         <cxxFunctionParameterDeclaredType>
       
   380                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   381                         </cxxFunctionParameterDeclaredType>
       
   382                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   383                         <apiDefNote/>
       
   384                     </cxxFunctionParameter>
       
   385                 </cxxFunctionParameters>
       
   386                 <cxxFunctionAPIItemLocation>
       
   387                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   388                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   389                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   390                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   391                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   392                 </cxxFunctionAPIItemLocation>
       
   393             </cxxFunctionDefinition>
       
   394             <apiDesc/>
       
   395         </cxxFunctionDetail>
       
   396     </cxxFunction>
       
   397         </cxxClass>"""
       
   398         returned = self.link_file.get_linkified(file_as_string)
       
   399         self.assertEquals(etree.fromstring(returned).find("cxxFunction/apiName").attrib["id"], "BTrace::Init0()")
       
   400 
       
   401         
       
   402     def test__insert_a_guidised_id_into_cxxfunction_apiname(self):
       
   403         self.link_file = LinkFile(guidise=True)
       
   404         func_str = """<cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   405         <apiName>Init0</apiName>
       
   406         <shortdesc/>
       
   407         <cxxFunctionDetail>
       
   408             <cxxFunctionDefinition>
       
   409                 <cxxFunctionAccessSpecifier value="public"/>
       
   410                 <cxxFunctionStorageClassSpecifierStatic/>
       
   411                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   412                 <cxxFunctionScopedName>BTrace</cxxFunctionScopedName>
       
   413                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   414                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   415                 <cxxFunctionParameters>
       
   416                     <cxxFunctionParameter>
       
   417                         <cxxFunctionParameterDeclaredType>
       
   418                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   419                         </cxxFunctionParameterDeclaredType>
       
   420                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   421                         <apiDefNote/>
       
   422                     </cxxFunctionParameter>
       
   423                 </cxxFunctionParameters>
       
   424                 <cxxFunctionAPIItemLocation>
       
   425                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   426                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   427                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   428                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   429                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   430                 </cxxFunctionAPIItemLocation>
       
   431             </cxxFunctionDefinition>
       
   432             <apiDesc/>
       
   433         </cxxFunctionDetail>
       
   434     </cxxFunction>"""
       
   435         func_elem = etree.fromstring(func_str)
       
   436         returned = self.link_file._insert_id_into_cxxfunction_apiname(func_elem)
       
   437         self.assertEquals(returned.find("apiName").attrib["id"], "GUID-C8A77671-4E2F-3290-9592-84A70B14F88D")
       
   438 
       
   439     def test__insert_a_guidised_id_into_cxxfunction_apiname_when_the_cxxfunction_has_no_scoped_name(self):
       
   440         self.link_file = LinkFile(guidise=True)
       
   441         func_str = """<cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   442         <apiName>Init0</apiName>
       
   443         <shortdesc/>
       
   444         <cxxFunctionDetail>
       
   445             <cxxFunctionDefinition>
       
   446                 <cxxFunctionAccessSpecifier value="public"/>
       
   447                 <cxxFunctionStorageClassSpecifierStatic/>
       
   448                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   449                 <cxxFunctionScopedName/>
       
   450                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   451                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   452                 <cxxFunctionParameters>
       
   453                     <cxxFunctionParameter>
       
   454                         <cxxFunctionParameterDeclaredType>
       
   455                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   456                         </cxxFunctionParameterDeclaredType>
       
   457                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   458                         <apiDefNote/>
       
   459                     </cxxFunctionParameter>
       
   460                 </cxxFunctionParameters>
       
   461                 <cxxFunctionAPIItemLocation>
       
   462                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   463                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   464                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   465                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   466                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   467                 </cxxFunctionAPIItemLocation>
       
   468             </cxxFunctionDefinition>
       
   469             <apiDesc/>
       
   470         </cxxFunctionDetail>
       
   471     </cxxFunction>"""
       
   472         func_elem = etree.fromstring(func_str)
       
   473         returned = self.link_file._insert_id_into_cxxfunction_apiname(func_elem)
       
   474         self.assertEquals(returned.find("apiName").attrib["id"], "GUID-76C4A377-8597-3952-9E6B-3E61D068EE38")
       
   475         
       
   476     def test_i_can_insert_a_guidised_id_to_a_cxxfunction_apiname(self):
       
   477         self.link_file = LinkFile(guidise=True)
       
   478         file_as_string = """    
       
   479         <cxxClass>
       
   480 <cxxFunction id="class_b_trace_1a7217f2fa88e99af3dbb5827fdc8507b7">
       
   481         <apiName>Init0</apiName>
       
   482         <shortdesc/>
       
   483         <cxxFunctionDetail>
       
   484             <cxxFunctionDefinition>
       
   485                 <cxxFunctionAccessSpecifier value="public"/>
       
   486                 <cxxFunctionStorageClassSpecifierStatic/>
       
   487                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   488                 <cxxFunctionScopedName>BTrace</cxxFunctionScopedName>
       
   489                 <cxxFunctionPrototype>static void Init0(TUint32 a0)</cxxFunctionPrototype>
       
   490                 <cxxFunctionNameLookup>BTrace::Init0(TUint32 a0)</cxxFunctionNameLookup>
       
   491                 <cxxFunctionParameters>
       
   492                     <cxxFunctionParameter>
       
   493                         <cxxFunctionParameterDeclaredType>
       
   494                             <apiRelation keyref="_always_online_manager_client_8cpp_1a8240e11f17c80b6b222fc2af50234da4">TUint32</apiRelation>
       
   495                         </cxxFunctionParameterDeclaredType>
       
   496                         <cxxFunctionParameterDeclarationName>a0</cxxFunctionParameterDeclarationName>
       
   497                         <apiDefNote/>
       
   498                     </cxxFunctionParameter>
       
   499                 </cxxFunctionParameters>
       
   500                 <cxxFunctionAPIItemLocation>
       
   501                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   502                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   503                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   504                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   505                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   506                 </cxxFunctionAPIItemLocation>
       
   507             </cxxFunctionDefinition>
       
   508             <apiDesc/>
       
   509         </cxxFunctionDetail>
       
   510     </cxxFunction>
       
   511         </cxxClass>"""
       
   512         returned = self.link_file.get_linkified(file_as_string)
       
   513         self.assertEquals(etree.fromstring(returned).find("cxxFunction/apiName").attrib["id"], "GUID-C8A77671-4E2F-3290-9592-84A70B14F88D")
       
   514         
       
   515 basic_class_file_str = """\    
       
   516 <cxxClass>
       
   517     <cxxFunction id="function_id">
       
   518         <apiName>Init0</apiName>
       
   519         <shortdesc/>
       
   520         <cxxFunctionDetail>
       
   521             <cxxFunctionDefinition>
       
   522                 <cxxFunctionAccessSpecifier value="public"/>
       
   523                 <cxxFunctionStorageClassSpecifierStatic/>
       
   524                 <cxxFunctionDeclaredType>void</cxxFunctionDeclaredType>
       
   525                 <cxxFunctionScopedName>BTrace</cxxFunctionScopedName>
       
   526                 <cxxFunctionPrototype>static void Init0()</cxxFunctionPrototype>
       
   527                 <cxxFunctionNameLookup>BTrace::Init0()</cxxFunctionNameLookup>
       
   528                 <cxxFunctionParameters/>
       
   529                 <cxxFunctionAPIItemLocation>
       
   530                     <cxxFunctionDeclarationFile name="filePath" value="D:/epoc32/include/e32btrace.h"/>
       
   531                     <cxxFunctionDeclarationFileLine name="lineNumber" value="3882"/>
       
   532                     <cxxFunctionDefinitionFile name="filePath" value="D:/EPOC/master/sf/mw/messagingmw/messagingfw/alwaysonline/AlwaysOnlineManager/src/AlwaysOnlineManagerClient.cpp"/>
       
   533                     <cxxFunctionDefinitionFileLineStart name="lineNumber" value="-1"/>
       
   534                     <cxxFunctionDefinitionFileLineEnd name="lineNumber" value="-1"/>
       
   535                 </cxxFunctionAPIItemLocation>
       
   536             </cxxFunctionDefinition>
       
   537             <apiDesc/>
       
   538         </cxxFunctionDetail>
       
   539     </cxxFunction>
       
   540 </cxxClass>"""
       
   541 
       
   542 
       
   543 xml_files = {
       
   544                "basic_xml_file_1.xml": """<tag1></tag1>""",
       
   545                "basic_xml_file_2.xml": """<tag2></tag2>""",
       
   546                }
       
   547 no_xml_files = {
       
   548                "non_xml_file.txt": """Some text""",                     
       
   549                }
       
   550 
       
   551 
       
   552 class DummyLinkFile(object):
       
   553     
       
   554     def __init__(self):
       
   555         self.visited_files = []
       
   556     
       
   557     def get_linkified(self, file_as_string):
       
   558         self.visited_files.append(file_as_string)
       
   559         return file_as_string
       
   560         
       
   561 class TestLinkInserter(unittest.TestCase):
       
   562     
       
   563     def setUp(self):
       
   564         self.dummy_link_file = DummyLinkFile()
       
   565         self.inserter = LinkInserter(self.dummy_link_file)
       
   566         
       
   567     def test__handle_xml_file_writes_to_a_file(self):
       
   568         tmp_file_path = os.getcwd() + os.sep + "tmp_file.xml"
       
   569         tmp_file = open(tmp_file_path, "w")
       
   570         tmp_file.write(basic_class_file_str)
       
   571         tmp_file.close()
       
   572         self.inserter._handle_xml_file(tmp_file_path)
       
   573         self.assertEquals(self.dummy_link_file.visited_files, [basic_class_file_str])
       
   574         os.remove(tmp_file_path)
       
   575         
       
   576     def test_i_raise_an_exception_when_dir_doesnt_exist(self):
       
   577         self.assertRaises(IOError, self.inserter.linkify_dir, "non_existant_dir")
       
   578         
       
   579     def test_i_call_linkify_on_each_file_xml_file_in_a_dir(self):
       
   580         basic_files = {}
       
   581         basic_files.update(xml_files)
       
   582         basic_files.update(no_xml_files)
       
   583         test_dir = os.path.join(os.getcwd(), "test_dir")
       
   584         os.mkdir(test_dir)
       
   585         for filename,file_content in basic_files.items():
       
   586             handle = open(os.path.join(test_dir, filename),"w")
       
   587             handle.write(file_content)
       
   588             handle.close()
       
   589         self.inserter._do_linkifying(test_dir)
       
   590         self.dummy_link_file.visited_files.sort()
       
   591         xml_files_input = xml_files.values()
       
   592         xml_files_input.sort()
       
   593         self.assertEquals(self.dummy_link_file.visited_files, xml_files_input)      
       
   594         shutil.rmtree(test_dir)