view paraspace/tests/injection_test.py @ 100:355986e5cfbd

Make surce methods of injected class are also being and bug fixed. - dex_type_2_array_attr_map() misses marked array attributes. - It is fixed by skiping marked array and use back type instead.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 26 Jul 2011 10:06:44 +0800
parents 3898711adb2c
children f14c32108164
line wrap: on
line source

from paraspace import dexfile
import os

def _install_dexfile_4_deptracker():
    global dexfile
    import imp, sys
    from paraspace import dex_deptracker
    
    try:
        new_dexfile = imp.load_compiled('dexfile', dexfile.__file__)
    except ImportError:
        new_dexfile = imp.load_source('dexfile', dexfile.__file__)
        pass
    dex_deptracker.dexfile = new_dexfile
    dexfile = new_dexfile
    dex_deptracker._nest_types = (dexfile.array, dexfile.cond, dexfile.switch)
    
    sys.modules['paraspace.dexfile'] = new_dexfile
    pass


def _find_map(dex, map_type):
    for map in dex.maps.items.items:
        if map.type == map_type:
            return map
        pass
    pass


def inject_fakefile_to_helloworld_test():
    from paraspace.dex_deptracker import prepare_dep_decls
    from paraspace.injection import dexfile_insert_class
    
    _install_dexfile_4_deptracker()
    
    all_dep_decls = prepare_dep_decls()
    
    srcdir = os.path.dirname(__file__)
    srcroot = os.path.join(srcdir, '..', '..')
    
    helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex')
    helloworld_dex = dexfile.DEXFile.open(helloworld_fn)

    classdef_map = _find_map(helloworld_dex, 0x0006)
    saved_classdef_map_sz = classdef_map.size
    saved_methodids_sz = len(helloworld_dex.methodIds.items)
    
    codeitems_map = _find_map(helloworld_dex, 0x2001)
    saved_codeitems_sz = codeitems_map.size

    helloworld_linked = \
        dexfile.DEXFile_linked.build_dependencies(helloworld_dex,
                                                  all_dep_decls)

    fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex')
    fakefile_dex = dexfile.DEXFile.open(fakefile_fn)
    fakefile_linked = \
        dexfile.DEXFile_linked. \
        build_dependencies(fakefile_dex, all_dep_decls)
    
    fakefile_def = fakefile_linked. \
        find_class_name('Lcom/codemud/fakefile/fakefile;')

    fakefile_data = fakefile_def.classDataOffRef.value
    assert len(fakefile_data.directMethods.items) == 1
    assert len(fakefile_data.virtualMethods.items) == 0
    fakefile_dataheader = fakefile_data.header
    assert fakefile_dataheader.directMethodsSize == 1
    assert fakefile_dataheader.virtualMethodsSize == 0

    clone = dexfile_insert_class(helloworld_linked, fakefile_def)
    assert clone
    assert clone != fakefile_def

    helloworld_unlinked = helloworld_linked.get_unlinked()
    assert helloworld_unlinked

    # map size for classdef must be increased by 1
    classdef_map = _find_map(helloworld_unlinked, 0x0006)
    assert classdef_map.size == saved_classdef_map_sz + 1

    classdata_map = _find_map(helloworld_unlinked, 0x2000)
    assert classdata_map.size == classdef_map.size

    # Check strings
    strdatas = helloworld_unlinked.stringDataItems.items
    strs = sorted([strdata.data.data for strdata in strdatas])
    assert len(strs) == len(set(strs)) # uniquely
    assert 'Lcom/codemud/fakefile/fakefile;' in strs

    # Check Method List
    methodids_map = _find_map(helloworld_unlinked, 0x0005) # method ids
    assert methodids_map.size == len(helloworld_unlinked.methodIds.items)
    assert methodids_map.size == saved_methodids_sz + 1

    # Check Code item List
    codeitems_map = _find_map(helloworld_unlinked, 0x2001)
    assert codeitems_map.size == saved_codeitems_sz + 1
    pass