[pygccxml-commit] SF.net SVN: pygccxml: [477] pygccxml_dev/unittests
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-08-27 06:52:42
|
Revision: 477 Author: roman_yakovenko Date: 2006-08-26 23:52:22 -0700 (Sat, 26 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=477&view=rev Log Message: ----------- adding unit tests for algorithms cache Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/algorithm.py pygccxml_dev/pygccxml/declarations/algorithms_cache.py pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/pygccxml/declarations/declaration.py pygccxml_dev/pygccxml/utils/__init__.py pygccxml_dev/unittests/test_all.py Added Paths: ----------- pygccxml_dev/unittests/algorithms_cache_tester.py Modified: pygccxml_dev/pygccxml/declarations/algorithm.py =================================================================== --- pygccxml_dev/pygccxml/declarations/algorithm.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/pygccxml/declarations/algorithm.py 2006-08-27 06:52:22 UTC (rev 477) @@ -10,16 +10,19 @@ def declaration_path( decl ): """ returns a list of parent declarations names - + @param decl: declaration for which declaration path should be calculated @type decl: L{declaration_t} - - @return: [names], where first item contains top parent name and last item + + @return: [names], where first item contains top parent name and last item contains decl name """ + #TODO: + #If parent declaration cache already has declaration_path, reuse it for + #calculation. if not decl: return [] - if not decl.cache.declaration_path: + if not decl.cache.declaration_path: result = [ decl.name ] parent = decl.parent while parent: @@ -27,27 +30,32 @@ parent = parent.parent result.reverse() decl.cache.declaration_path = result - return decl.cache.declaration_path + return result + else: + return decl.cache.declaration_path def full_name( decl ): """ returns full name of the declaration - @param decl: declaration for which full name should be calculated. If decl + @param decl: declaration for which full name should be calculated. If decl belongs to unnamed namespace, then L{full_name} is not valid C++ full name. - + @type decl: L{declaration_t} - @return: full name of declarations. + @return: full name of declarations. """ if None is decl: raise RuntimeError( "Unable to generate full name for None object!" ) if not decl.cache.full_name: decl_path = declaration_path( decl ) - ##Here I have lack of knowledge: + ##Here I have lack of knowledge: ##TODO: "What is the full name of declaration declared in unnamed namespace?" result = filter( None, decl_path ) - decl.cache.full_name = result[0] + '::'.join( result[1:] ) - return decl.cache.full_name + result = result[0] + '::'.join( result[1:] ) + decl.cache.full_name = result + return result + else: + return decl.cache.full_name def make_flatten( decl_or_decls ): @@ -56,7 +64,7 @@ @param decl_or_decls: reference to list of declaration's or single declaration @type decl_or_decls: L{declaration_t} or [ L{declaration_t} ] - + @return: [ all internal declarations ] """ import pygccxml.declarations #prevent cyclic import @@ -78,7 +86,7 @@ decls.append( decl_or_decls ) answer = [] for decl in decls: - answer.extend( proceed_single( decl ) ) + answer.extend( proceed_single( decl ) ) return answer def __make_flatten_generator( decl_or_decls ): @@ -87,10 +95,10 @@ @param decl_or_decls: reference to list of declaration's or single declaration @type decl_or_decls: L{declaration_t} or [ L{declaration_t} ] - + @return: [ all internal declarations ] """ - + import pygccxml.declarations def proceed_single( decl ): yield decl @@ -113,24 +121,24 @@ def get_global_namespace(decls): import pygccxml.declarations - found = filter( lambda decl: decl.name == '::' + found = filter( lambda decl: decl.name == '::' and isinstance( decl, pygccxml.declarations.namespace_t ) , make_flatten( decls ) ) if len( found ) == 1: return found[0] raise RuntimeError( "Unable to find global namespace." ) - + class match_declaration_t: """ - helper class for different search algorithms. - + helper class for different search algorithms. + This class will help developer to match declaration by: - declaration type, for example L{class_t} or L{operator_t}. - declaration name - declaration full name - reference to parent declaration """ - + def __init__( self, type=None, name=None, fullname=None, parent=None ): self.type = type self.name = name @@ -140,10 +148,10 @@ def does_match_exist(self, inst): """ returns True if inst do match one of specified criteria - + @param inst: declaration instance @type inst: L{declaration_t} - + @return: bool """ answer = True @@ -169,12 +177,12 @@ , name=None , parent=None , recursive=True - , fullname=None ): + , fullname=None ): """ returns a list of all declarations that match criteria, defined by developer - + For more information about arguments see L{match_declaration_t} class. - + @return: [ matched declarations ] """ decls = [] @@ -192,13 +200,13 @@ , recursive=True , fullname=None ): """ - returns single declaration that match criteria, defined by developer. + returns single declaration that match criteria, defined by developer. If more the one declaration was found None will be returned. - + For more information about arguments see L{match_declaration_t} class. - + @return: matched declaration L{declaration_t} or None - """ + """ decl = find_all_declarations( declarations, type=type, name=name, parent=parent, recursive=recursive, fullname=fullname ) if len( decl ) == 1: return decl[0] @@ -206,31 +214,31 @@ def find_first_declaration( declarations, type=None, name=None, parent=None, recursive=True, fullname=None ): """ returns first declaration that match criteria, defined by developer - + For more information about arguments see L{match_declaration_t} class. - + @return: matched declaration L{declaration_t} or None """ matcher = match_declaration_t(type, name, fullname, parent) if recursive: decls = make_flatten( declarations ) else: - decls = declarations + decls = declarations for decl in decls: if matcher( decl ): return decl return None - + def declaration_files(decl_or_decls): """ returns set of files - + Every declaration is declared in some file. This function returns set, that contains all file names of declarations. - + @param decl_or_decls: reference to list of declaration's or single declaration @type decl_or_decls: L{declaration_t} or [ L{declaration_t} ] - + @return: set( declaration file names ) """ files = set() @@ -242,9 +250,9 @@ class visit_function_has_not_been_found_t( RuntimeError ): """ - exception that is raised, from L{apply_visitor}, when a visitor could not be + exception that is raised, from L{apply_visitor}, when a visitor could not be applied. - + """ def __init__( self, visitor, decl_inst ): RuntimeError.__init__( self ) @@ -257,7 +265,7 @@ def apply_visitor( visitor, decl_inst): """ applies a visitor on declaration instance - + @param visitor: instance @type visitor: L{type_visitor_t} or L{decl_visitor_t} """ Modified: pygccxml_dev/pygccxml/declarations/algorithms_cache.py =================================================================== --- pygccxml_dev/pygccxml/declarations/algorithms_cache.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/pygccxml/declarations/algorithms_cache.py 2006-08-27 06:52:22 UTC (rev 477) @@ -10,24 +10,83 @@ class algorithms_cache_t( object ): def __init__( self ): object.__init__( self ) - self.full_name = None - self.access_type = None - self.declaration_path = None - + self._enabled = True + + def disable( self ): + self._enabled = False + + def enable( self ): + self._enabled = True + + @property + def enabled( self ): + return self._enabled + +class declaration_algs_cache_t( algorithms_cache_t ): + def __init__( self ): + algorithms_cache_t.__init__( self ) + self._full_name = None + self._access_type = None + self._demangled_name = None + self._declaration_path = None + + def _get_full_name( self ): + if self.enabled: + return self._full_name + return None + def _set_full_name( self, fname ): + self._full_name = fname + full_name = property( _get_full_name, _set_full_name ) + + def _get_access_type( self ): + if self.enabled: + return self._access_type + return None + def _set_access_type( self, access_type ): + self._access_type = access_type + access_type = property( _get_access_type, _set_access_type ) + + def _get_demangled_name( self ): + if self.enabled: + return self._demangled_name + return None + def _set_demangled_name( self, demangled_name ): + self._demangled_name = demangled_name + demangled_name = property( _get_demangled_name, _set_demangled_name ) + + def _get_declaration_path( self ): + if self.enabled: + return self._declaration_path + return None + def _set_declaration_path( self, declaration_path ): + self._declaration_path = declaration_path + declaration_path = property( _get_declaration_path, _set_declaration_path ) + def reset( self ): self.full_name = None self.access_type = None + self.demangled_name = None self.declaration_path = None def reset_name_based( self ): self.full_name = None + self.demangled_name = None self.declaration_path = None - + def reset_access_type( self ): self.access_type = None - -class type_traits_cache_t( object ): - def __init__( self ): - object.__init__( self ) - self.remove_alias = None - + +#Introducing next cache to the type broke unit test. I should find out why. +#~ class type_algs_cache_t( algorithms_cache_t ): + #~ def __init__( self ): + #~ algorithms_cache_t.__init__( self ) + #~ self._remove_alias = None + + #~ def _get_remove_alias( self ): + #~ if self.enabled: + #~ return self._remove_alias + #~ return None + #~ def _set_remove_alias( self, remove_alias ): + #~ self._remove_alias = remove_alias + #~ remove_alias = property( _get_remove_alias, _set_remove_alias ) + Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-08-27 06:52:22 UTC (rev 477) @@ -101,13 +101,12 @@ self._private_members = [] self._protected_members = [] self._aliases = [] - self.__cached_demangled_name = None # Cached value of name from get_name_impl def _get_name_impl( self ): if not self._name: #class with empty name return self._name elif class_t.USE_DEMANGLED_AS_NAME and self.demangled: - if not self.__cached_demangled_name: + if not self.cache.demangled_name: fname = algorithm.full_name( self.parent ) if fname.startswith( '::' ) and not self.demangled.startswith( '::' ): fname = fname[2:] @@ -115,10 +114,13 @@ tmp = self.demangled[ len( fname ): ] #demangled::name if tmp.startswith( '::' ): tmp = tmp[2:] - self.__cached_demangled_name = tmp + self.cache.demangled_name = tmp + return tmp else: - self.__cached_demangled_name = self._name - return self.__cached_demangled_name + self.cache.demangled_name = self._name + return self._name + else: + return self.cache.demangled_name else: return self._name @@ -301,7 +303,7 @@ container = self.private_members del container[ container.index( decl ) ] decl.cache.reset_access_type() - + def find_out_member_access_type( self, member ): """ returns member access type @@ -311,16 +313,19 @@ @return: L{ACCESS_TYPES} """ - assert member.parent is self + assert member.parent is self if not member.cache.access_type: access_type = None if member in self.public_members: - member.cache.access_type = ACCESS_TYPES.PUBLIC + access_type = ACCESS_TYPES.PUBLIC elif member in self.protected_members: - member.cache.access_type = ACCESS_TYPES.PROTECTED + access_type = ACCESS_TYPES.PROTECTED elif member in self.private_members: - member.cache.access_type = ACCESS_TYPES.PRIVATE + access_type = ACCESS_TYPES.PRIVATE else: raise RuntimeError( "Unable to find member within internal members list." ) - return member.cache.access_type - + member.cache.access_type = access_type + return access_type + else: + return member.cache.access_type + Modified: pygccxml_dev/pygccxml/declarations/declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/declaration.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/pygccxml/declarations/declaration.py 2006-08-27 06:52:22 UTC (rev 477) @@ -75,7 +75,7 @@ self._mangled = mangled self._demangled = demangled self._parent = None - self._cache = algorithms_cache.algorithms_cache_t() + self._cache = algorithms_cache.declaration_algs_cache_t() def __str__(self): """Default __str__ method. @@ -164,9 +164,10 @@ def _set_name( self, new_name ): previous_name = self._name self._name = new_name + self.cache.reset_name_based() if previous_name: #the was a rename and not initial "set" self._on_rename() - + name = property( _get_name, _set_name , doc="""Declaration name @type: str @@ -248,4 +249,4 @@ reference to instance of L{algorithms_cache.algorithms_cache_t} class. """ - return self._cache \ No newline at end of file + return self._cache Modified: pygccxml_dev/pygccxml/utils/__init__.py =================================================================== --- pygccxml_dev/pygccxml/utils/__init__.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/pygccxml/utils/__init__.py 2006-08-27 06:52:22 UTC (rev 477) @@ -13,44 +13,44 @@ import logging import tempfile -def _create_logger_( name ): +def _create_logger_( name ): """implementation details""" logger = logging.getLogger(name) handler = logging.StreamHandler(sys.stdout) handler.setFormatter( logging.Formatter( os.linesep + '%(levelname)s %(message)s' ) ) - logger.addHandler(handler) + logger.addHandler(handler) logger.setLevel(logging.INFO) return logger class loggers: """class-namespace, defines few loggers classes, used in the project""" - gccxml = _create_logger_( 'pygccxml.gccxml' ) + gccxml = _create_logger_( 'pygccxml.gccxml' ) """logger for gccxml functionality - + If you set this logger level to DEBUG, you will be able to see the exact command line, used to invoke GCC-XML and errors that occures during XML parsing """ - + queries_engine = _create_logger_( 'pygccxml.queries_engine' ) """logger for query engine functionality. - + If you set this logger level to DEBUG, you will be able to see what queries you do against declarations tree, measure performance and may be even to improve it. Query engine reports queries and whether they are optimized or not. """ - + declarations_cache = _create_logger_( 'pygccxml.declarations_cache' ) """logger for declarations tree cache functionality - + If you set this logger level to DEBUG, you will be able to see what is exactly - happens, when you read the declarations from cache file. You will be able to + happens, when you read the declarations from cache file. You will be able to decide, whether it worse for you to use this or that cache strategy. """ - + root = logging.getLogger( 'pygccxml' ) """root logger exists for your convinience only""" - + all = [ root, gccxml, queries_engine, declarations_cache ] """contains all logger classes, defined by the class""" @@ -60,12 +60,12 @@ if os.path.exists(file_name): os.remove( file_name ) except Exception, error: - loggers.root.error( "Error ocured while removing temprorary created file('%s'): %s" + loggers.root.error( "Error ocured while removing temprorary created file('%s'): %s" % ( file_name, str( error ) ) ) -def create_temp_file_name(suffix, prefix=None, dir=None): +def create_temp_file_name(suffix, prefix=None, dir=None): """small convinience function that creates temporal file. - + This function is a wrapper aroung Python built-in function - tempfile.mkstemp """ if not prefix: @@ -79,9 +79,9 @@ """return os.path.normpath( os.path.normcase( some_path ) )""" return os.path.normpath( os.path.normcase( some_path ) ) -def get_architecture(): +def get_architecture(): """returns computer architecture: 32 or 64. - + The guess is based on maxint. """ if sys.maxint == 2147483647: @@ -89,4 +89,5 @@ elif sys.maxint == 9223372036854775807: return 64 else: - raise RuntimeError( "Unknown architecture" ) \ No newline at end of file + raise RuntimeError( "Unknown architecture" ) + Added: pygccxml_dev/unittests/algorithms_cache_tester.py =================================================================== --- pygccxml_dev/unittests/algorithms_cache_tester.py (rev 0) +++ pygccxml_dev/unittests/algorithms_cache_tester.py 2006-08-27 06:52:22 UTC (rev 477) @@ -0,0 +1,75 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import unittest +import autoconfig +import parser_test_case + +from pygccxml import utils +from pygccxml import parser +from pygccxml import declarations + +class algorithms_cache_tester_t( parser_test_case.parser_test_case_t ): + #tester source reader + COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE + def __init__(self, *args ): + parser_test_case.parser_test_case_t.__init__( self, *args ) + self.header = 'core_membership.hpp' + self.global_ns = None + + def setUp(self): + decls = parser.parse( [self.header], self.config ) + self.global_ns = declarations.get_global_namespace( decls ) + + def test_name_based( self ): + cls = self.global_ns.class_( name='class_for_nested_enums_t' ) + + cls_demangled_name = cls.name + self.failUnless( cls.cache.demangled_name == cls_demangled_name ) + + cls_full_name = declarations.full_name( cls ) + self.failUnless( cls.cache.full_name == cls_full_name ) + + cls_declaration_path = declarations.declaration_path( cls ) + self.failUnless( cls.cache.declaration_path == cls_declaration_path ) + + enum = cls.enum( 'ENestedPublic' ) + + enum_full_name = declarations.full_name( enum ) + self.failUnless( enum.cache.full_name == enum_full_name ) + + enum_declaration_path = declarations.declaration_path( enum ) + self.failUnless( enum.cache.declaration_path == enum_declaration_path ) + + #now we change class name, all internal decls cache should be cleared + cls.name = "new_name" + self.failUnless( not cls.cache.full_name ) + self.failUnless( not cls.cache.demangled_name ) + self.failUnless( not cls.cache.declaration_path ) + + self.failUnless( not enum.cache.full_name ) + self.failUnless( not enum.cache.demangled_name ) + self.failUnless( not enum.cache.declaration_path ) + + def test_access_type( self ): + cls = self.global_ns.class_( name='class_for_nested_enums_t' ) + enum = cls.enum( 'ENestedPublic' ) + self.failUnless( enum.cache.access_type == 'public' ) + enum.cache.reset_access_type() + self.failUnless( not enum.cache.access_type ) + self.failUnless( 'public' == cls.find_out_member_access_type( enum ) ) + self.failUnless( enum.cache.access_type == 'public' ) + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(algorithms_cache_tester_t)) + + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() Modified: pygccxml_dev/unittests/test_all.py =================================================================== --- pygccxml_dev/unittests/test_all.py 2006-08-26 18:27:22 UTC (rev 476) +++ pygccxml_dev/unittests/test_all.py 2006-08-27 06:52:22 UTC (rev 477) @@ -17,7 +17,7 @@ import type_traits_tester import core_tester import xmlfile_reader_tester -import filtering_tester +import filtering_tester import text_reader_tester import hierarchy_traveling import patcher_tester @@ -31,16 +31,17 @@ import filters_tester import cache_enums_tester import decl_printer_tester -import typedefs_tester +import typedefs_tester import demangled_tester import unnamed_enums_bug_tester import vector_traits_tester import string_traits_tester import declarations_cache_tester import has_binary_operator_traits_tester +import algorithms_cache_tester def create_suite(): - testers = [ + testers = [ decl_string_tester , declaration_files_tester , declarations_comparison_tester @@ -75,14 +76,15 @@ , string_traits_tester , declarations_cache_tester , has_binary_operator_traits_tester + , algorithms_cache_tester ] - - main_suite = unittest.TestSuite() + + main_suite = unittest.TestSuite() for tester in testers: main_suite.addTest( tester.create_suite() ) return main_suite - + def run_suite(): result = unittest.TextTestRunner(verbosity=2).run( create_suite() ) error_desc = 'EXCEPTION IN SAFE SELECT 9' @@ -104,4 +106,4 @@ ##~ statistics = hotshot.stats.load( statistics_file ) ##~ statistics.strip_dirs() ##~ statistics.sort_stats( 'time', 'calls' ) -##~ statistics.print_stats( 678 ) \ No newline at end of file +##~ statistics.print_stats( 678 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |