import pytest from unittest.mock import Mock from unittest.mock import call from checksymbolslib.test_util import assert_db_calls import checksymbolslib.kconfig as m all_symbols_from = [ ('no prefix', 'config PACKAGE_FOO', []), ('simple', 'config BR2_PACKAGE_FOO', ['BR2_PACKAGE_FOO']), ('ignore comment', 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR', ['BR2_PACKAGE_FOO']), ('ignore whitespace', '\tconfig BR2_PACKAGE_FOO\t # BR2_PACKAGE_BAR', ['BR2_PACKAGE_FOO']), ('2 occurrences', '\tdefault BR2_PACKAGE_FOO_BAR if BR2_PACKAGE_FOO_BAR != ""', ['BR2_PACKAGE_FOO_BAR', 'BR2_PACKAGE_FOO_BAR']), ] @pytest.mark.parametrize('testname,line,expected', all_symbols_from) def test_all_symbols_from(testname, line, expected): symbols = m.all_symbols_from(line) assert symbols == expected handle_definition = [ ('config', 'package/foo/Config.in', 5, 'config BR2_PACKAGE_FOO', False, {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ('ignore comment', 'package/foo/Config.in', 5, 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR', False, {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ('ignore whitespace', 'package/foo/Config.in', 5, '\tconfig BR2_PACKAGE_FOO\t # BR2_PACKAGE_BAR', False, {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ('menuconfig', 'package/gd/Config.in', 1, 'menuconfig BR2_PACKAGE_GD', False, {'add_symbol_definition': [call('BR2_PACKAGE_GD', 'package/gd/Config.in', 1)]}), ('menu', 'package/Config.in', 100, 'menu "Database"', False, {}), ('legacy config', 'Config.in.legacy', 50, 'config BR2_PACKAGE_FOO', True, {'add_symbol_legacy_definition': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 50)]}), ] @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_definition) def test_handle_definition(testname, filename, lineno, line, legacy, expected_calls): db = Mock() m.handle_definition(db, filename, lineno, line, legacy) assert_db_calls(db, expected_calls) handle_usage = [ ('default with comparison', 'package/openblas/Config.in', 60, '\tdefault y if BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET != ""', False, {'add_symbol_usage': [call('BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET', 'package/openblas/Config.in', 60)]}), ('default with logical operators', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47, '\tdefault y if BR2_i386 && !BR2_x86_i486 && !BR2_x86_i586 && !BR2_x86_x1000 && !BR2_x86_pentium_mmx && !BR2_x86_geode ' '&& !BR2_x86_c3 && !BR2_x86_winchip_c6 && !BR2_x86_winchip2', False, {'add_symbol_usage': [ call('BR2_i386', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_c3', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_geode', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_i486', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_i586', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_pentium_mmx', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_winchip2', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_winchip_c6', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_x1000', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47)]}), ('legacy depends on', 'Config.in.legacy', 3000, '\tdepends on BR2_LINUX_KERNEL', True, {'add_symbol_usage_in_legacy': [call('BR2_LINUX_KERNEL', 'Config.in.legacy', 3000)]}), ('legacy if', 'Config.in.legacy', 97, 'if !BR2_SKIP_LEGACY', True, {'add_symbol_usage_in_legacy': [call('BR2_SKIP_LEGACY', 'Config.in.legacy', 97)]}), ('source', 'system/Config.in', 152, 'source "$BR2_BASE_DIR/.br2-external.in.init"', False, {'add_symbol_usage': [call('BR2_BASE_DIR', 'system/Config.in', 152)]}), ] @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_usage) def test_handle_usage(testname, filename, lineno, line, legacy, expected_calls): db = Mock() m.handle_usage(db, filename, lineno, line, legacy) assert_db_calls(db, expected_calls) handle_default = [ ('default with comparison', 'package/openblas/Config.in', 60, '\tdefault y if BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET != ""', False, {'add_symbol_usage': [call('BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET', 'package/openblas/Config.in', 60)]}), ('default with logical operators', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47, '\tdefault y if BR2_i386 && !BR2_x86_i486 && !BR2_x86_i586 && !BR2_x86_x1000 && !BR2_x86_pentium_mmx && !BR2_x86_geode ' '&& !BR2_x86_c3 && !BR2_x86_winchip_c6 && !BR2_x86_winchip2', False, {'add_symbol_usage': [ call('BR2_i386', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_c3', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_geode', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_i486', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_i586', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_pentium_mmx', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_winchip2', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_winchip_c6', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47), call('BR2_x86_x1000', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47)]}), ('legacy default', 'Config.in.legacy', 3000, 'default y if BR2_PACKAGE_REFPOLICY_POLICY_VERSION != ""', True, {'add_symbol_usage_in_legacy': [call('BR2_PACKAGE_REFPOLICY_POLICY_VERSION', 'Config.in.legacy', 3000)]}), ('legacy handling on package', 'package/uboot-tools/Config.in.host', 105, '\tdefault BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE if BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE != "" # legacy', False, {'add_symbol_legacy_usage': [call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105)]}), ('default on package', 'package/uboot-tools/Config.in.host', 105, '\tdefault BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE if BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE != ""', False, {'add_symbol_usage': [ call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105), call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105)]}), ] @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_default) def test_handle_default(testname, filename, lineno, line, legacy, expected_calls): db = Mock() m.handle_default(db, filename, lineno, line, legacy) assert_db_calls(db, expected_calls) handle_select = [ ('select with comparison', 'package/bcusdk/Config.in', 6, '\tselect BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL', False, {'add_symbol_select': [call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6)], 'add_symbol_usage': [ call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6), call('BR2_TOOLCHAIN_USES_UCLIBC', 'package/bcusdk/Config.in', 6), call('BR2_TOOLCHAIN_USES_MUSL', 'package/bcusdk/Config.in', 6)]}), ('legacy select', 'Config.in.legacy', 100, '\tselect BR2_PACKAGE_WPA_SUPPLICANT_DBUS if BR2_TOOLCHAIN_HAS_THREADS', True, {'add_symbol_select': [call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100)], 'add_symbol_usage_in_legacy': [ call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100), call('BR2_TOOLCHAIN_HAS_THREADS', 'Config.in.legacy', 100)]}), ] @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_select) def test_handle_select(testname, filename, lineno, line, legacy, expected_calls): db = Mock() m.handle_select(db, filename, lineno, line, legacy) assert_db_calls(db, expected_calls) handle_line = [ ('select with comparison', 'package/bcusdk/Config.in', 6, '\tselect BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL', False, {'add_symbol_select': [call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6)], 'add_symbol_usage': [ call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6), call('BR2_TOOLCHAIN_USES_UCLIBC', 'package/bcusdk/Config.in', 6), call('BR2_TOOLCHAIN_USES_MUSL', 'package/bcusdk/Config.in', 6)]}), ('legacy select', 'Config.in.legacy', 100, '\tselect BR2_PACKAGE_WPA_SUPPLICANT_DBUS if BR2_TOOLCHAIN_HAS_THREADS', True, {'add_symbol_select': [call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100)], 'add_symbol_usage_in_legacy': [ call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100), call('BR2_TOOLCHAIN_HAS_THREADS', 'Config.in.legacy', 100)]}), ('comment with symbol', 'Config.in', 6, '\tselect # BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL', False, {}), ('comment', 'Config.in', 6, '# just a comment', False, {}), ] @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_line) def test_handle_line(testname, filename, lineno, line, legacy, expected_calls): db = Mock() m.handle_line(db, filename, lineno, line, legacy) assert_db_calls(db, expected_calls) handle_config_helper = [ ('no select', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO']], {}), ('select', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO'], [6, '\tselect BR2_PACKAGE_BAR']], {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ('ignore comment', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR'], [6, '\tselect BR2_PACKAGE_BAR # BR2_PACKAGE_FOO']], {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ('correct symbol', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO'], [6, 'config BR2_PACKAGE_BAR'], [7, '\tselect BR2_PACKAGE_BAZ']], {'add_symbol_helper': [call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}), ('2 selects', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO'], [6, '\tselect BR2_PACKAGE_BAR'], [7, ' select BR2_PACKAGE_BAR']], {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}), ] @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_config_helper) def test_handle_config_helper(testname, filename, file_content, expected_calls): db = Mock() m.handle_config_helper(db, filename, file_content) assert_db_calls(db, expected_calls) handle_config_choice = [ ('no choice', 'package/foo/Config.in', [[5, 'config BR2_PACKAGE_FOO']], {}), ('after', 'package/foo/Config.in', [[3, 'choice'], [4, '\tprompt "your choice"'], [5, 'config BR2_PACKAGE_FOO'], [6, 'config BR2_PACKAGE_BAR'], [10, 'endchoice'], [19, 'config BR2_PACKAGE_BAZ']], {'add_symbol_choice': [ call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5), call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}), ('before', 'package/foo/Config.in', [[1, 'config BR2_PACKAGE_BAZ'], [3, 'choice'], [4, '\tprompt "your choice"'], [5, 'config BR2_PACKAGE_FOO'], [6, 'config BR2_PACKAGE_BAR'], [10, 'endchoice']], {'add_symbol_choice': [ call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5), call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}), ] @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_config_choice) def test_handle_config_choice(testname, filename, file_content, expected_calls): db = Mock() m.handle_config_choice(db, filename, file_content) assert_db_calls(db, expected_calls) handle_note = [ ('example', 'Config.in.legacy', [[51, '# # Note: BR2_FOO_1 is still referenced from package/foo/Config.in']], {}), ('ok', 'Config.in.legacy', [[112, 'menu "Legacy config options"'], [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'], [4958, 'endmenu']], {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)]}), ('before and after', 'Config.in.legacy', [[100, '# Note: BR2_PACKAGE_BAR is still referenced from package/foo/Config.in'], [112, 'menu "Legacy config options"'], [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'], [4958, 'endmenu'], [5000, '# Note: BR2_PACKAGE_BAR is still referenced from package/foo/Config.in']], {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)]}), ] @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_note) def test_handle_note(testname, filename, file_content, expected_calls): db = Mock() m.handle_note(db, filename, file_content) assert_db_calls(db, expected_calls) populate_db = [ ('legacy', 'Config.in.legacy', [[112, 'menu "Legacy config options"'], [2100, 'config BR2_PACKAGE_FOO'], [2101, '\tselect BR2_PACKAGE_BAR'], [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'], [4958, 'endmenu']], {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)], 'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2100)], 'add_symbol_legacy_definition': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2100)], 'add_symbol_usage_in_legacy': [call('BR2_PACKAGE_BAR', 'Config.in.legacy', 2101)], 'add_symbol_select': [call('BR2_PACKAGE_BAR', 'Config.in.legacy', 2101)]}), ('normal', 'package/foo/Config.in', [[1, 'config BR2_PACKAGE_BAZ'], [3, 'choice'], [4, '\tprompt "your choice"'], [5, 'config BR2_PACKAGE_FOO'], [6, 'config BR2_PACKAGE_BAR'], [7, '\t select BR2_PACKAGE_FOO_BAR'], [10, 'endchoice']], {'add_symbol_choice': [ call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5), call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)], 'add_symbol_usage': [ call('BR2_PACKAGE_FOO_BAR', 'package/foo/Config.in', 7)], 'add_symbol_select': [ call('BR2_PACKAGE_FOO_BAR', 'package/foo/Config.in', 7)], 'add_symbol_definition': [ call('BR2_PACKAGE_BAZ', 'package/foo/Config.in', 1), call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5), call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)], 'add_symbol_helper': [ call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}), ] @pytest.mark.parametrize('testname,filename,file_content,expected_calls', populate_db) def test_populate_db(testname, filename, file_content, expected_calls): db = Mock() m.populate_db(db, filename, file_content) assert_db_calls(db, expected_calls) check_filename = [ ('Config.in', 'Config.in', True), ('Config.in.legacy', 'Config.in.legacy', True), ('arch/Config.in.microblaze', 'arch/Config.in.microblaze', True), ('package/php/Config.ext', 'package/php/Config.ext', True), ('package/pru-software-support/Config.in.host', 'package/pru-software-support/Config.in.host', True), ('toolchain/toolchain-external/toolchain-external-custom/Config.in.options', 'toolchain/toolchain-external/toolchain-external-custom/Config.in.options', True), ('package/foo/0001-Config.patch', 'package/foo/0001-Config.patch', False), ('package/pkg-generic.mk', 'package/pkg-generic.mk', False), ('Makefile', 'Makefile', False), ] @pytest.mark.parametrize('testname,filename,expected', check_filename) def test_check_filename(testname, filename, expected): symbols = m.check_filename(filename) assert symbols == expected