test_kconfig.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. import pytest
  2. from unittest.mock import Mock
  3. from unittest.mock import call
  4. from checksymbolslib.test_util import assert_db_calls
  5. import checksymbolslib.kconfig as m
  6. all_symbols_from = [
  7. ('no prefix',
  8. 'config PACKAGE_FOO',
  9. []),
  10. ('simple',
  11. 'config BR2_PACKAGE_FOO',
  12. ['BR2_PACKAGE_FOO']),
  13. ('ignore comment',
  14. 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR',
  15. ['BR2_PACKAGE_FOO']),
  16. ('ignore whitespace',
  17. '\tconfig BR2_PACKAGE_FOO\t # BR2_PACKAGE_BAR',
  18. ['BR2_PACKAGE_FOO']),
  19. ('2 occurrences',
  20. '\tdefault BR2_PACKAGE_FOO_BAR if BR2_PACKAGE_FOO_BAR != ""',
  21. ['BR2_PACKAGE_FOO_BAR', 'BR2_PACKAGE_FOO_BAR']),
  22. ]
  23. @pytest.mark.parametrize('testname,line,expected', all_symbols_from)
  24. def test_all_symbols_from(testname, line, expected):
  25. symbols = m.all_symbols_from(line)
  26. assert symbols == expected
  27. handle_definition = [
  28. ('config',
  29. 'package/foo/Config.in',
  30. 5,
  31. 'config BR2_PACKAGE_FOO',
  32. False,
  33. {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  34. ('ignore comment',
  35. 'package/foo/Config.in',
  36. 5,
  37. 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR',
  38. False,
  39. {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  40. ('ignore whitespace',
  41. 'package/foo/Config.in',
  42. 5,
  43. '\tconfig BR2_PACKAGE_FOO\t # BR2_PACKAGE_BAR',
  44. False,
  45. {'add_symbol_definition': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  46. ('menuconfig',
  47. 'package/gd/Config.in',
  48. 1,
  49. 'menuconfig BR2_PACKAGE_GD',
  50. False,
  51. {'add_symbol_definition': [call('BR2_PACKAGE_GD', 'package/gd/Config.in', 1)]}),
  52. ('menu',
  53. 'package/Config.in',
  54. 100,
  55. 'menu "Database"',
  56. False,
  57. {}),
  58. ('legacy config',
  59. 'Config.in.legacy',
  60. 50,
  61. 'config BR2_PACKAGE_FOO',
  62. True,
  63. {'add_symbol_legacy_definition': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 50)]}),
  64. ]
  65. @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_definition)
  66. def test_handle_definition(testname, filename, lineno, line, legacy, expected_calls):
  67. db = Mock()
  68. m.handle_definition(db, filename, lineno, line, legacy)
  69. assert_db_calls(db, expected_calls)
  70. handle_usage = [
  71. ('default with comparison',
  72. 'package/openblas/Config.in',
  73. 60,
  74. '\tdefault y if BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET != ""',
  75. False,
  76. {'add_symbol_usage': [call('BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET', 'package/openblas/Config.in', 60)]}),
  77. ('default with logical operators',
  78. 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options',
  79. 47,
  80. '\tdefault y if BR2_i386 && !BR2_x86_i486 && !BR2_x86_i586 && !BR2_x86_x1000 && !BR2_x86_pentium_mmx && !BR2_x86_geode '
  81. '&& !BR2_x86_c3 && !BR2_x86_winchip_c6 && !BR2_x86_winchip2',
  82. False,
  83. {'add_symbol_usage': [
  84. call('BR2_i386', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  85. call('BR2_x86_c3', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  86. call('BR2_x86_geode', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  87. call('BR2_x86_i486', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  88. call('BR2_x86_i586', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  89. call('BR2_x86_pentium_mmx', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  90. call('BR2_x86_winchip2', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  91. call('BR2_x86_winchip_c6', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  92. call('BR2_x86_x1000', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47)]}),
  93. ('legacy depends on',
  94. 'Config.in.legacy',
  95. 3000,
  96. '\tdepends on BR2_LINUX_KERNEL',
  97. True,
  98. {'add_symbol_usage_in_legacy': [call('BR2_LINUX_KERNEL', 'Config.in.legacy', 3000)]}),
  99. ('legacy if',
  100. 'Config.in.legacy',
  101. 97,
  102. 'if !BR2_SKIP_LEGACY',
  103. True,
  104. {'add_symbol_usage_in_legacy': [call('BR2_SKIP_LEGACY', 'Config.in.legacy', 97)]}),
  105. ('source',
  106. 'system/Config.in',
  107. 152,
  108. 'source "$BR2_BASE_DIR/.br2-external.in.init"',
  109. False,
  110. {'add_symbol_usage': [call('BR2_BASE_DIR', 'system/Config.in', 152)]}),
  111. ]
  112. @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_usage)
  113. def test_handle_usage(testname, filename, lineno, line, legacy, expected_calls):
  114. db = Mock()
  115. m.handle_usage(db, filename, lineno, line, legacy)
  116. assert_db_calls(db, expected_calls)
  117. handle_default = [
  118. ('default with comparison',
  119. 'package/openblas/Config.in',
  120. 60,
  121. '\tdefault y if BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET != ""',
  122. False,
  123. {'add_symbol_usage': [call('BR2_PACKAGE_OPENBLAS_DEFAULT_TARGET', 'package/openblas/Config.in', 60)]}),
  124. ('default with logical operators',
  125. 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options',
  126. 47,
  127. '\tdefault y if BR2_i386 && !BR2_x86_i486 && !BR2_x86_i586 && !BR2_x86_x1000 && !BR2_x86_pentium_mmx && !BR2_x86_geode '
  128. '&& !BR2_x86_c3 && !BR2_x86_winchip_c6 && !BR2_x86_winchip2',
  129. False,
  130. {'add_symbol_usage': [
  131. call('BR2_i386', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  132. call('BR2_x86_c3', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  133. call('BR2_x86_geode', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  134. call('BR2_x86_i486', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  135. call('BR2_x86_i586', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  136. call('BR2_x86_pentium_mmx', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  137. call('BR2_x86_winchip2', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  138. call('BR2_x86_winchip_c6', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47),
  139. call('BR2_x86_x1000', 'toolchain/toolchain-external/toolchain-external-bootlin/Config.in.options', 47)]}),
  140. ('legacy default',
  141. 'Config.in.legacy',
  142. 3000,
  143. 'default y if BR2_PACKAGE_REFPOLICY_POLICY_VERSION != ""',
  144. True,
  145. {'add_symbol_usage_in_legacy': [call('BR2_PACKAGE_REFPOLICY_POLICY_VERSION', 'Config.in.legacy', 3000)]}),
  146. ('legacy handling on package',
  147. 'package/uboot-tools/Config.in.host',
  148. 105,
  149. '\tdefault BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE if BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE != "" # legacy',
  150. False,
  151. {'add_symbol_legacy_usage': [call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105)]}),
  152. ('default on package',
  153. 'package/uboot-tools/Config.in.host',
  154. 105,
  155. '\tdefault BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE if BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE != ""',
  156. False,
  157. {'add_symbol_usage': [
  158. call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105),
  159. call('BR2_TARGET_UBOOT_BOOT_SCRIPT_SOURCE', 'package/uboot-tools/Config.in.host', 105)]}),
  160. ]
  161. @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_default)
  162. def test_handle_default(testname, filename, lineno, line, legacy, expected_calls):
  163. db = Mock()
  164. m.handle_default(db, filename, lineno, line, legacy)
  165. assert_db_calls(db, expected_calls)
  166. handle_select = [
  167. ('select with comparison',
  168. 'package/bcusdk/Config.in',
  169. 6,
  170. '\tselect BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL',
  171. False,
  172. {'add_symbol_select': [call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6)],
  173. 'add_symbol_usage': [
  174. call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6),
  175. call('BR2_TOOLCHAIN_USES_UCLIBC', 'package/bcusdk/Config.in', 6),
  176. call('BR2_TOOLCHAIN_USES_MUSL', 'package/bcusdk/Config.in', 6)]}),
  177. ('legacy select',
  178. 'Config.in.legacy',
  179. 100,
  180. '\tselect BR2_PACKAGE_WPA_SUPPLICANT_DBUS if BR2_TOOLCHAIN_HAS_THREADS',
  181. True,
  182. {'add_symbol_select': [call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100)],
  183. 'add_symbol_usage_in_legacy': [
  184. call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100),
  185. call('BR2_TOOLCHAIN_HAS_THREADS', 'Config.in.legacy', 100)]}),
  186. ]
  187. @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_select)
  188. def test_handle_select(testname, filename, lineno, line, legacy, expected_calls):
  189. db = Mock()
  190. m.handle_select(db, filename, lineno, line, legacy)
  191. assert_db_calls(db, expected_calls)
  192. handle_line = [
  193. ('select with comparison',
  194. 'package/bcusdk/Config.in',
  195. 6,
  196. '\tselect BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL',
  197. False,
  198. {'add_symbol_select': [call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6)],
  199. 'add_symbol_usage': [
  200. call('BR2_PACKAGE_ARGP_STANDALONE', 'package/bcusdk/Config.in', 6),
  201. call('BR2_TOOLCHAIN_USES_UCLIBC', 'package/bcusdk/Config.in', 6),
  202. call('BR2_TOOLCHAIN_USES_MUSL', 'package/bcusdk/Config.in', 6)]}),
  203. ('legacy select',
  204. 'Config.in.legacy',
  205. 100,
  206. '\tselect BR2_PACKAGE_WPA_SUPPLICANT_DBUS if BR2_TOOLCHAIN_HAS_THREADS',
  207. True,
  208. {'add_symbol_select': [call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100)],
  209. 'add_symbol_usage_in_legacy': [
  210. call('BR2_PACKAGE_WPA_SUPPLICANT_DBUS', 'Config.in.legacy', 100),
  211. call('BR2_TOOLCHAIN_HAS_THREADS', 'Config.in.legacy', 100)]}),
  212. ('comment with symbol',
  213. 'Config.in',
  214. 6,
  215. '\tselect # BR2_PACKAGE_ARGP_STANDALONE if BR2_TOOLCHAIN_USES_UCLIBC || BR2_TOOLCHAIN_USES_MUSL',
  216. False,
  217. {}),
  218. ('comment',
  219. 'Config.in',
  220. 6,
  221. '# just a comment',
  222. False,
  223. {}),
  224. ]
  225. @pytest.mark.parametrize('testname,filename,lineno,line,legacy,expected_calls', handle_line)
  226. def test_handle_line(testname, filename, lineno, line, legacy, expected_calls):
  227. db = Mock()
  228. m.handle_line(db, filename, lineno, line, legacy)
  229. assert_db_calls(db, expected_calls)
  230. handle_config_helper = [
  231. ('no select',
  232. 'package/foo/Config.in',
  233. [[5, 'config BR2_PACKAGE_FOO']],
  234. {}),
  235. ('select',
  236. 'package/foo/Config.in',
  237. [[5, 'config BR2_PACKAGE_FOO'],
  238. [6, '\tselect BR2_PACKAGE_BAR']],
  239. {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  240. ('ignore comment',
  241. 'package/foo/Config.in',
  242. [[5, 'config BR2_PACKAGE_FOO # BR2_PACKAGE_BAR'],
  243. [6, '\tselect BR2_PACKAGE_BAR # BR2_PACKAGE_FOO']],
  244. {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  245. ('correct symbol',
  246. 'package/foo/Config.in',
  247. [[5, 'config BR2_PACKAGE_FOO'],
  248. [6, 'config BR2_PACKAGE_BAR'],
  249. [7, '\tselect BR2_PACKAGE_BAZ']],
  250. {'add_symbol_helper': [call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}),
  251. ('2 selects',
  252. 'package/foo/Config.in',
  253. [[5, 'config BR2_PACKAGE_FOO'],
  254. [6, '\tselect BR2_PACKAGE_BAR'],
  255. [7, ' select BR2_PACKAGE_BAR']],
  256. {'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5)]}),
  257. ]
  258. @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_config_helper)
  259. def test_handle_config_helper(testname, filename, file_content, expected_calls):
  260. db = Mock()
  261. m.handle_config_helper(db, filename, file_content)
  262. assert_db_calls(db, expected_calls)
  263. handle_config_choice = [
  264. ('no choice',
  265. 'package/foo/Config.in',
  266. [[5, 'config BR2_PACKAGE_FOO']],
  267. {}),
  268. ('after',
  269. 'package/foo/Config.in',
  270. [[3, 'choice'],
  271. [4, '\tprompt "your choice"'],
  272. [5, 'config BR2_PACKAGE_FOO'],
  273. [6, 'config BR2_PACKAGE_BAR'],
  274. [10, 'endchoice'],
  275. [19, 'config BR2_PACKAGE_BAZ']],
  276. {'add_symbol_choice': [
  277. call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5),
  278. call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}),
  279. ('before',
  280. 'package/foo/Config.in',
  281. [[1, 'config BR2_PACKAGE_BAZ'],
  282. [3, 'choice'],
  283. [4, '\tprompt "your choice"'],
  284. [5, 'config BR2_PACKAGE_FOO'],
  285. [6, 'config BR2_PACKAGE_BAR'],
  286. [10, 'endchoice']],
  287. {'add_symbol_choice': [
  288. call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5),
  289. call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}),
  290. ]
  291. @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_config_choice)
  292. def test_handle_config_choice(testname, filename, file_content, expected_calls):
  293. db = Mock()
  294. m.handle_config_choice(db, filename, file_content)
  295. assert_db_calls(db, expected_calls)
  296. handle_note = [
  297. ('example',
  298. 'Config.in.legacy',
  299. [[51, '# # Note: BR2_FOO_1 is still referenced from package/foo/Config.in']],
  300. {}),
  301. ('ok',
  302. 'Config.in.legacy',
  303. [[112, 'menu "Legacy config options"'],
  304. [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'],
  305. [4958, 'endmenu']],
  306. {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)]}),
  307. ('before and after',
  308. 'Config.in.legacy',
  309. [[100, '# Note: BR2_PACKAGE_BAR is still referenced from package/foo/Config.in'],
  310. [112, 'menu "Legacy config options"'],
  311. [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'],
  312. [4958, 'endmenu'],
  313. [5000, '# Note: BR2_PACKAGE_BAR is still referenced from package/foo/Config.in']],
  314. {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)]}),
  315. ]
  316. @pytest.mark.parametrize('testname,filename,file_content,expected_calls', handle_note)
  317. def test_handle_note(testname, filename, file_content, expected_calls):
  318. db = Mock()
  319. m.handle_note(db, filename, file_content)
  320. assert_db_calls(db, expected_calls)
  321. populate_db = [
  322. ('legacy',
  323. 'Config.in.legacy',
  324. [[112, 'menu "Legacy config options"'],
  325. [2100, 'config BR2_PACKAGE_FOO'],
  326. [2101, '\tselect BR2_PACKAGE_BAR'],
  327. [2132, '# Note: BR2_PACKAGE_FOO is still referenced from package/foo/Config.in'],
  328. [4958, 'endmenu']],
  329. {'add_symbol_legacy_note': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2132)],
  330. 'add_symbol_helper': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2100)],
  331. 'add_symbol_legacy_definition': [call('BR2_PACKAGE_FOO', 'Config.in.legacy', 2100)],
  332. 'add_symbol_usage_in_legacy': [call('BR2_PACKAGE_BAR', 'Config.in.legacy', 2101)],
  333. 'add_symbol_select': [call('BR2_PACKAGE_BAR', 'Config.in.legacy', 2101)]}),
  334. ('normal',
  335. 'package/foo/Config.in',
  336. [[1, 'config BR2_PACKAGE_BAZ'],
  337. [3, 'choice'],
  338. [4, '\tprompt "your choice"'],
  339. [5, 'config BR2_PACKAGE_FOO'],
  340. [6, 'config BR2_PACKAGE_BAR'],
  341. [7, '\t select BR2_PACKAGE_FOO_BAR'],
  342. [10, 'endchoice']],
  343. {'add_symbol_choice': [
  344. call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5),
  345. call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)],
  346. 'add_symbol_usage': [
  347. call('BR2_PACKAGE_FOO_BAR', 'package/foo/Config.in', 7)],
  348. 'add_symbol_select': [
  349. call('BR2_PACKAGE_FOO_BAR', 'package/foo/Config.in', 7)],
  350. 'add_symbol_definition': [
  351. call('BR2_PACKAGE_BAZ', 'package/foo/Config.in', 1),
  352. call('BR2_PACKAGE_FOO', 'package/foo/Config.in', 5),
  353. call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)],
  354. 'add_symbol_helper': [
  355. call('BR2_PACKAGE_BAR', 'package/foo/Config.in', 6)]}),
  356. ]
  357. @pytest.mark.parametrize('testname,filename,file_content,expected_calls', populate_db)
  358. def test_populate_db(testname, filename, file_content, expected_calls):
  359. db = Mock()
  360. m.populate_db(db, filename, file_content)
  361. assert_db_calls(db, expected_calls)
  362. check_filename = [
  363. ('Config.in',
  364. 'Config.in',
  365. True),
  366. ('Config.in.legacy',
  367. 'Config.in.legacy',
  368. True),
  369. ('arch/Config.in.microblaze',
  370. 'arch/Config.in.microblaze',
  371. True),
  372. ('package/php/Config.ext',
  373. 'package/php/Config.ext',
  374. True),
  375. ('package/pru-software-support/Config.in.host',
  376. 'package/pru-software-support/Config.in.host',
  377. True),
  378. ('toolchain/toolchain-external/toolchain-external-custom/Config.in.options',
  379. 'toolchain/toolchain-external/toolchain-external-custom/Config.in.options',
  380. True),
  381. ('package/foo/0001-Config.patch',
  382. 'package/foo/0001-Config.patch',
  383. False),
  384. ('package/pkg-generic.mk',
  385. 'package/pkg-generic.mk',
  386. False),
  387. ('Makefile',
  388. 'Makefile',
  389. False),
  390. ]
  391. @pytest.mark.parametrize('testname,filename,expected', check_filename)
  392. def test_check_filename(testname, filename, expected):
  393. symbols = m.check_filename(filename)
  394. assert symbols == expected