test_stm32cubeprogrammer.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. # Copyright (c) 2020 Teslabs Engineering S.L.
  2. #
  3. # SPDX-License-Identifier: Apache-2.0
  4. import argparse
  5. from pathlib import Path
  6. from unittest.mock import patch, call
  7. import pytest
  8. from runners.stm32cubeprogrammer import STM32CubeProgrammerBinaryRunner
  9. from conftest import RC_KERNEL_HEX, RC_KERNEL_ELF
  10. CLI_PATH = Path("STM32_Programmer_CLI")
  11. """Default CLI path used in tests."""
  12. HOME_PATH = Path("/home", "test")
  13. """Home path (used for Linux system CLI path)."""
  14. PROGRAMFILESX86_PATH = Path("C:", "Program Files (x86)")
  15. """Program files x86 path (used for Windows system CLI path)."""
  16. ENVIRON = {
  17. "PROGRAMFILES(X86)": str(PROGRAMFILESX86_PATH),
  18. }
  19. """Environment (used for Windows system CLI path)."""
  20. LINUX_CLI_PATH = (
  21. HOME_PATH
  22. / "STMicroelectronics"
  23. / "STM32Cube"
  24. / "STM32CubeProgrammer"
  25. / "bin"
  26. / "STM32_Programmer_CLI"
  27. )
  28. """Linux CLI path."""
  29. WINDOWS_CLI_PATH = (
  30. PROGRAMFILESX86_PATH
  31. / "STMicroelectronics"
  32. / "STM32Cube"
  33. / "STM32CubeProgrammer"
  34. / "bin"
  35. / "STM32_Programmer_CLI.exe"
  36. )
  37. """Windows CLI path."""
  38. MACOS_CLI_PATH = (
  39. Path("/Applications")
  40. / "STMicroelectronics"
  41. / "STM32Cube"
  42. / "STM32CubeProgrammer"
  43. / "STM32CubeProgrammer.app"
  44. / "Contents"
  45. / "MacOs"
  46. / "bin"
  47. / "STM32_Programmer_CLI"
  48. )
  49. """macOS CLI path."""
  50. TEST_CASES = (
  51. {
  52. "port": "swd",
  53. "frequency": None,
  54. "reset_mode": None,
  55. "conn_modifiers": None,
  56. "cli": CLI_PATH,
  57. "use_elf": False,
  58. "erase": False,
  59. "tool_opt": [],
  60. "system": "",
  61. "cli_path": str(CLI_PATH),
  62. "calls": [
  63. [
  64. str(CLI_PATH),
  65. "--connect",
  66. "port=swd",
  67. "--download",
  68. RC_KERNEL_HEX,
  69. "--start",
  70. ],
  71. ],
  72. },
  73. {
  74. "port": "swd",
  75. "frequency": "4000",
  76. "reset_mode": None,
  77. "conn_modifiers": None,
  78. "cli": CLI_PATH,
  79. "use_elf": False,
  80. "erase": False,
  81. "tool_opt": [],
  82. "system": "",
  83. "cli_path": str(CLI_PATH),
  84. "calls": [
  85. [
  86. str(CLI_PATH),
  87. "--connect",
  88. "port=swd freq=4000",
  89. "--download",
  90. RC_KERNEL_HEX,
  91. "--start",
  92. ],
  93. ],
  94. },
  95. {
  96. "port": "swd",
  97. "frequency": None,
  98. "reset_mode": "hw",
  99. "conn_modifiers": None,
  100. "cli": CLI_PATH,
  101. "use_elf": False,
  102. "erase": False,
  103. "tool_opt": [],
  104. "system": "",
  105. "cli_path": str(CLI_PATH),
  106. "calls": [
  107. [
  108. str(CLI_PATH),
  109. "--connect",
  110. "port=swd reset=HWrst",
  111. "--download",
  112. RC_KERNEL_HEX,
  113. "--start",
  114. ],
  115. ],
  116. },
  117. {
  118. "port": "swd",
  119. "frequency": None,
  120. "reset_mode": "sw",
  121. "conn_modifiers": None,
  122. "cli": CLI_PATH,
  123. "use_elf": False,
  124. "erase": False,
  125. "tool_opt": [],
  126. "system": "",
  127. "cli_path": str(CLI_PATH),
  128. "calls": [
  129. [
  130. str(CLI_PATH),
  131. "--connect",
  132. "port=swd reset=SWrst",
  133. "--download",
  134. RC_KERNEL_HEX,
  135. "--start",
  136. ],
  137. ],
  138. },
  139. {
  140. "port": "swd",
  141. "frequency": None,
  142. "reset_mode": "core",
  143. "conn_modifiers": None,
  144. "cli": CLI_PATH,
  145. "use_elf": False,
  146. "erase": False,
  147. "tool_opt": [],
  148. "system": "",
  149. "cli_path": str(CLI_PATH),
  150. "calls": [
  151. [
  152. str(CLI_PATH),
  153. "--connect",
  154. "port=swd reset=Crst",
  155. "--download",
  156. RC_KERNEL_HEX,
  157. "--start",
  158. ],
  159. ],
  160. },
  161. {
  162. "port": "swd",
  163. "frequency": None,
  164. "reset_mode": None,
  165. "conn_modifiers": "br=115200 sn=TEST",
  166. "cli": CLI_PATH,
  167. "use_elf": False,
  168. "erase": False,
  169. "tool_opt": [],
  170. "system": "",
  171. "cli_path": str(CLI_PATH),
  172. "calls": [
  173. [
  174. str(CLI_PATH),
  175. "--connect",
  176. "port=swd br=115200 sn=TEST",
  177. "--download",
  178. RC_KERNEL_HEX,
  179. "--start",
  180. ],
  181. ],
  182. },
  183. {
  184. "port": "swd",
  185. "frequency": None,
  186. "reset_mode": None,
  187. "conn_modifiers": None,
  188. "cli": CLI_PATH,
  189. "use_elf": True,
  190. "erase": False,
  191. "tool_opt": [],
  192. "system": "",
  193. "cli_path": str(CLI_PATH),
  194. "calls": [
  195. [
  196. str(CLI_PATH),
  197. "--connect",
  198. "port=swd",
  199. "--download",
  200. RC_KERNEL_ELF,
  201. "--start",
  202. ],
  203. ],
  204. },
  205. {
  206. "port": "swd",
  207. "frequency": None,
  208. "reset_mode": None,
  209. "conn_modifiers": None,
  210. "cli": CLI_PATH,
  211. "use_elf": False,
  212. "erase": True,
  213. "tool_opt": [],
  214. "system": "",
  215. "cli_path": str(CLI_PATH),
  216. "calls": [
  217. [str(CLI_PATH), "--connect", "port=swd", "--erase", "all",],
  218. [
  219. str(CLI_PATH),
  220. "--connect",
  221. "port=swd",
  222. "--download",
  223. RC_KERNEL_HEX,
  224. "--start",
  225. ],
  226. ],
  227. },
  228. {
  229. "port": "swd",
  230. "frequency": None,
  231. "reset_mode": None,
  232. "conn_modifiers": None,
  233. "cli": CLI_PATH,
  234. "use_elf": False,
  235. "erase": False,
  236. "tool_opt": ["--skipErase"],
  237. "system": "",
  238. "cli_path": str(CLI_PATH),
  239. "calls": [
  240. [
  241. str(CLI_PATH),
  242. "--connect",
  243. "port=swd",
  244. "--skipErase",
  245. "--download",
  246. RC_KERNEL_HEX,
  247. "--start",
  248. ],
  249. ],
  250. },
  251. {
  252. "port": "swd",
  253. "frequency": None,
  254. "reset_mode": None,
  255. "conn_modifiers": None,
  256. "cli": None,
  257. "use_elf": False,
  258. "erase": False,
  259. "tool_opt": [],
  260. "system": "Linux",
  261. "cli_path": str(LINUX_CLI_PATH),
  262. "calls": [
  263. [
  264. str(LINUX_CLI_PATH),
  265. "--connect",
  266. "port=swd",
  267. "--download",
  268. RC_KERNEL_HEX,
  269. "--start",
  270. ],
  271. ],
  272. },
  273. {
  274. "port": "swd",
  275. "frequency": None,
  276. "reset_mode": None,
  277. "conn_modifiers": None,
  278. "cli": None,
  279. "use_elf": False,
  280. "erase": False,
  281. "tool_opt": [],
  282. "system": "Darwin",
  283. "cli_path": str(MACOS_CLI_PATH),
  284. "calls": [
  285. [
  286. str(MACOS_CLI_PATH),
  287. "--connect",
  288. "port=swd",
  289. "--download",
  290. RC_KERNEL_HEX,
  291. "--start",
  292. ],
  293. ],
  294. },
  295. {
  296. "port": "swd",
  297. "frequency": None,
  298. "reset_mode": None,
  299. "conn_modifiers": None,
  300. "cli": None,
  301. "use_elf": False,
  302. "erase": False,
  303. "tool_opt": [],
  304. "system": "Windows",
  305. "cli_path": str(WINDOWS_CLI_PATH),
  306. "calls": [
  307. [
  308. str(WINDOWS_CLI_PATH),
  309. "--connect",
  310. "port=swd",
  311. "--download",
  312. RC_KERNEL_HEX,
  313. "--start",
  314. ],
  315. ],
  316. },
  317. )
  318. """Test cases."""
  319. @pytest.mark.parametrize("tc", TEST_CASES)
  320. @patch("runners.stm32cubeprogrammer.platform.system")
  321. @patch("runners.stm32cubeprogrammer.Path.home", return_value=HOME_PATH)
  322. @patch("runners.stm32cubeprogrammer.Path.exists", return_value=True)
  323. @patch.dict("runners.stm32cubeprogrammer.os.environ", ENVIRON)
  324. @patch("runners.core.ZephyrBinaryRunner.require")
  325. @patch("runners.stm32cubeprogrammer.STM32CubeProgrammerBinaryRunner.check_call")
  326. def test_stm32cubeprogrammer_init(
  327. check_call, require, path_exists, path_home, system, tc, runner_config
  328. ):
  329. """Tests that ``STM32CubeProgrammerBinaryRunner`` class can be initialized
  330. and that ``flash`` command works as expected.
  331. """
  332. system.return_value = tc["system"]
  333. runner = STM32CubeProgrammerBinaryRunner(
  334. cfg=runner_config,
  335. port=tc["port"],
  336. frequency=tc["frequency"],
  337. reset_mode=tc["reset_mode"],
  338. conn_modifiers=tc["conn_modifiers"],
  339. cli=tc["cli"],
  340. use_elf=tc["use_elf"],
  341. erase=tc["erase"],
  342. tool_opt=tc["tool_opt"],
  343. )
  344. runner.run("flash")
  345. require.assert_called_with(tc["cli_path"])
  346. assert check_call.call_args_list == [call(x) for x in tc["calls"]]
  347. @pytest.mark.parametrize("tc", TEST_CASES)
  348. @patch("runners.stm32cubeprogrammer.platform.system")
  349. @patch("runners.stm32cubeprogrammer.Path.home", return_value=HOME_PATH)
  350. @patch("runners.stm32cubeprogrammer.Path.exists", return_value=True)
  351. @patch.dict("runners.stm32cubeprogrammer.os.environ", ENVIRON)
  352. @patch("runners.core.ZephyrBinaryRunner.require")
  353. @patch("runners.stm32cubeprogrammer.STM32CubeProgrammerBinaryRunner.check_call")
  354. def test_stm32cubeprogrammer_create(
  355. check_call, require, path_exists, path_home, system, tc, runner_config
  356. ):
  357. """Tests that ``STM32CubeProgrammerBinaryRunner`` class can be created using
  358. the ``create`` factory method and that ``flash`` command works as expected.
  359. """
  360. system.return_value = tc["system"]
  361. args = ["--port", tc["port"]]
  362. if tc["frequency"]:
  363. args.extend(["--frequency", tc["frequency"]])
  364. if tc["reset_mode"]:
  365. args.extend(["--reset", tc["reset_mode"]])
  366. if tc["conn_modifiers"]:
  367. args.extend(["--conn-modifiers", tc["conn_modifiers"]])
  368. if tc["cli"]:
  369. args.extend(["--cli", str(tc["cli"])])
  370. if tc["use_elf"]:
  371. args.extend(["--use-elf"])
  372. if tc["erase"]:
  373. args.append("--erase")
  374. if tc["tool_opt"]:
  375. args.extend(["--tool-opt", " " + tc["tool_opt"][0]])
  376. parser = argparse.ArgumentParser()
  377. STM32CubeProgrammerBinaryRunner.add_parser(parser)
  378. arg_namespace = parser.parse_args(args)
  379. runner = STM32CubeProgrammerBinaryRunner.create(runner_config, arg_namespace)
  380. runner.run("flash")
  381. require.assert_called_with(tc["cli_path"])
  382. assert check_call.call_args_list == [call(x) for x in tc["calls"]]