1# Copyright (c) 2019 Thomas Kupper
2#
3# SPDX-License-Identifier: Apache-2.0
4
5import argparse
6import os
7import platform
8from unittest.mock import patch, call
9
10import pytest
11
12from runners.stm32flash import Stm32flashBinaryRunner
13from conftest import RC_KERNEL_BIN
14
15TEST_CMD = 'stm32flash'
16
17TEST_DEVICE = '/dev/ttyUSB0'
18if platform.system() == 'Darwin':
19    TEST_DEVICE = '/dev/tty.SLAB_USBtoUART'
20TEST_BAUD = '115200'
21TEST_FORCE_BINARY = False
22TEST_ADDR = '0x08000000'
23TEST_BIN_SIZE = '4095'
24TEST_EXEC_ADDR = '0'
25TEST_SERIAL_MODE = '8e1'
26TEST_RESET = False
27TEST_VERIFY = False
28
29# Expected subprocesses to be run for each action. Using the
30# runner_config fixture (and always specifying all necessary
31# parameters) means we don't get 100% coverage, but it's a
32# starting out point.
33EXPECTED_COMMANDS = {
34    'info':
35    ([TEST_CMD,
36      '-b', TEST_BAUD,
37      '-m', TEST_SERIAL_MODE,
38      TEST_DEVICE],),
39    'erase':
40    ([TEST_CMD,
41      '-b', TEST_BAUD,
42      '-m', TEST_SERIAL_MODE,
43      '-S', TEST_ADDR + ":" + str((int(TEST_BIN_SIZE)  >> 12) + 1 << 12),
44      '-o', TEST_DEVICE],),
45    'start':
46    ([TEST_CMD,
47      '-b', TEST_BAUD,
48      '-m', TEST_SERIAL_MODE,
49      '-g', TEST_EXEC_ADDR, TEST_DEVICE],),
50
51    'write':
52    ([TEST_CMD,
53      '-b', TEST_BAUD,
54      '-m', TEST_SERIAL_MODE,
55      '-S', TEST_ADDR + ":" + TEST_BIN_SIZE,
56      '-w', RC_KERNEL_BIN,
57      TEST_DEVICE],),
58}
59
60def require_patch(program):
61    assert program == TEST_CMD
62
63def os_path_getsize_patch(filename):
64    if filename == RC_KERNEL_BIN:
65        return TEST_BIN_SIZE
66    return os.path.isfile(filename)
67
68os_path_isfile = os.path.isfile
69
70def os_path_isfile_patch(filename):
71    if filename == RC_KERNEL_BIN:
72        return True
73    return os_path_isfile(filename)
74
75@pytest.mark.parametrize('action', EXPECTED_COMMANDS)
76@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
77@patch('runners.core.ZephyrBinaryRunner.check_call')
78def test_stm32flash_init(cc, req, action, runner_config):
79    '''Test actions using a runner created by constructor.'''
80    test_exec_addr = TEST_EXEC_ADDR
81    if action == 'write':
82        test_exec_addr = None
83
84    runner = Stm32flashBinaryRunner(runner_config, device=TEST_DEVICE,
85                 action=action, baud=TEST_BAUD, force_binary=TEST_FORCE_BINARY,
86                 start_addr=TEST_ADDR, exec_addr=test_exec_addr,
87                 serial_mode=TEST_SERIAL_MODE, reset=TEST_RESET, verify=TEST_VERIFY)
88
89    with patch('os.path.getsize', side_effect=os_path_getsize_patch):
90        with patch('os.path.isfile', side_effect=os_path_isfile_patch):
91            runner.run('flash')
92    assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[action]]
93
94@pytest.mark.parametrize('action', EXPECTED_COMMANDS)
95@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
96@patch('runners.core.ZephyrBinaryRunner.check_call')
97def test_stm32flash_create(cc, req, action, runner_config):
98    '''Test actions using a runner created from action line parameters.'''
99    if action == 'start':
100        args = ['--action', action, '--baud-rate', TEST_BAUD, '--start-addr', TEST_ADDR,
101                '--execution-addr', TEST_EXEC_ADDR]
102    else:
103        args = ['--action', action, '--baud-rate', TEST_BAUD, '--start-addr', TEST_ADDR]
104
105    parser = argparse.ArgumentParser(allow_abbrev=False)
106    Stm32flashBinaryRunner.add_parser(parser)
107    arg_namespace = parser.parse_args(args)
108    runner = Stm32flashBinaryRunner.create(runner_config, arg_namespace)
109    with patch('os.path.getsize', side_effect=os_path_getsize_patch):
110        with patch('os.path.isfile', side_effect=os_path_isfile_patch):
111            runner.run('flash')
112    assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[action]]
113