import nose
import angr

import logging
l = logging.getLogger("angr.tests.test_bindiff")

import os
test_location = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'binaries', 'tests')

# todo make a better test
def test_bindiff_x86_64():
    binary_path_1 = os.path.join(test_location, 'x86_64', 'bindiff_a')
    binary_path_2 = os.path.join(test_location, 'x86_64', 'bindiff_b')
    b = angr.Project(binary_path_1, load_options={"auto_load_libs": False})
    b2 = angr.Project(binary_path_2, load_options={"auto_load_libs": False})
    bindiff = b.analyses.BinDiff(b2)

    identical_functions = bindiff.identical_functions
    differing_functions = bindiff.differing_functions
    unmatched_functions = bindiff.unmatched_functions
    # check identical functions
    nose.tools.assert_in((0x40064c, 0x40066a), identical_functions)
    # check differing functions
    nose.tools.assert_in((0x400616, 0x400616), differing_functions)
    # check unmatched functions
    nose.tools.assert_less_equal(len(unmatched_functions[0]), 1)
    nose.tools.assert_less_equal(len(unmatched_functions[1]), 2)
    # check for no major regressions
    nose.tools.assert_greater(len(identical_functions), len(differing_functions))
    nose.tools.assert_less(len(differing_functions), 4)

    # check a function diff
    fdiff = bindiff.get_function_diff(0x400616, 0x400616)
    block_matches = { (a.addr, b.addr) for a, b in fdiff.block_matches }
    nose.tools.assert_in((0x40064a, 0x400668), block_matches)
    nose.tools.assert_in((0x400616, 0x400616), block_matches)
    nose.tools.assert_in((0x40061e, 0x40061e), block_matches)

def run_all():
    functions = globals()
    all_functions = dict(filter((lambda kv: kv[0].startswith('test_')), functions.items()))
    for f in sorted(all_functions.keys()):
        if hasattr(all_functions[f], '__call__'):
            all_functions[f]()

if __name__ == "__main__":
    logging.getLogger("angr.analyses.bindiff").setLevel(logging.DEBUG)

    import sys
    if len(sys.argv) > 1:
        globals()['test_' + sys.argv[1]]()
    else:
        run_all()

[((5, 4, 5, 48), 'logging.getLogger', 'logging.getLogger', ({(5, 22, 5, 47): '"""angr.tests.test_bindiff"""'}, {}), "('angr.tests.test_bindiff')", False, 'import logging\n'), ((12, 20, 12, 70), 'os.path.join', 'os.path.join', ({(12, 33, 12, 46): 'test_location', (12, 48, 12, 56): '"""x86_64"""', (12, 58, 12, 69): '"""bindiff_a"""'}, {}), "(test_location, 'x86_64', 'bindiff_a')", False, 'import os\n'), ((13, 20, 13, 70), 'os.path.join', 'os.path.join', ({(13, 33, 13, 46): 'test_location', (13, 48, 13, 56): '"""x86_64"""', (13, 58, 13, 69): '"""bindiff_b"""'}, {}), "(test_location, 'x86_64', 'bindiff_b')", False, 'import os\n'), ((14, 8, 14, 75), 'angr.Project', 'angr.Project', (), '', False, 'import angr\n'), ((15, 9, 15, 76), 'angr.Project', 'angr.Project', (), '', False, 'import angr\n'), ((22, 4, 22, 67), 'nose.tools.assert_in', 'nose.tools.assert_in', ({(22, 25, 22, 45): '(4195916, 4195946)', (22, 47, 22, 66): 'identical_functions'}, {}), '((4195916, 4195946), identical_functions)', False, 'import nose\n'), ((24, 4, 24, 67), 'nose.tools.assert_in', 'nose.tools.assert_in', ({(24, 25, 24, 45): '(4195862, 4195862)', (24, 47, 24, 66): 'differing_functions'}, {}), '((4195862, 4195862), differing_functions)', False, 'import nose\n'), ((35, 4, 35, 61), 'nose.tools.assert_in', 'nose.tools.assert_in', ({(35, 25, 35, 45): '(4195914, 4195944)', (35, 47, 35, 60): 'block_matches'}, {}), '((4195914, 4195944), block_matches)', False, 'import nose\n'), ((36, 4, 36, 61), 'nose.tools.assert_in', 'nose.tools.assert_in', ({(36, 25, 36, 45): '(4195862, 4195862)', (36, 47, 36, 60): 'block_matches'}, {}), '((4195862, 4195862), block_matches)', False, 'import nose\n'), ((37, 4, 37, 61), 'nose.tools.assert_in', 'nose.tools.assert_in', ({(37, 25, 37, 45): '(4195870, 4195870)', (37, 47, 37, 60): 'block_matches'}, {}), '((4195870, 4195870), block_matches)', False, 'import nose\n'), ((8, 45, 8, 71), 'os.path.realpath', 'os.path.realpath', ({(8, 62, 8, 70): '__file__'}, {}), '(__file__)', False, 'import os\n'), ((47, 4, 47, 46), 'logging.getLogger', 'logging.getLogger', ({(47, 22, 47, 45): '"""angr.analyses.bindiff"""'}, {}), "('angr.analyses.bindiff')", False, 'import logging\n')]