1# Copyright (c) 2020 Synopsys
2#
3# SPDX-License-Identifier: Apache-2.0
4
5import argparse
6from os import path, fspath
7from unittest.mock import patch
8from unittest.mock import call
9
10import pytest
11
12from runners.mdb import MdbNsimBinaryRunner, MdbHwBinaryRunner
13from conftest import RC_KERNEL_ELF, RC_BOARD_DIR, RC_BUILD_DIR
14
15
16TEST_DRIVER_CMD = 'mdb64'
17TEST_NSIM_ARGS='test_nsim.args'
18TEST_TARGET = 'test-target'
19TEST_BOARD_NSIM_ARGS = '@' + path.join(RC_BOARD_DIR, 'support', TEST_NSIM_ARGS)
20
21DOTCONFIG_HOSTLINK = f'''
22CONFIG_ARC=y
23CONFIG_UART_HOSTLINK=y
24'''
25
26DOTCONFIG_NO_HOSTLINK = f'''
27CONFIG_ARC=y
28'''
29
30# mdb-nsim
31TEST_NSIM_FLASH_CASES = [
32    {
33        'i': ['--cores=1', '--nsim_args=' + TEST_NSIM_ARGS],
34        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
35           '-toggle=include_local_symbols=1',
36           '-nsim', TEST_BOARD_NSIM_ARGS,
37           '-run', '-cl', RC_KERNEL_ELF]
38    }]
39
40TEST_NSIM_DEBUG_CASES = [
41    {
42        'i': ['--cores=1', '--nsim_args=' + TEST_NSIM_ARGS],
43        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
44           '-toggle=include_local_symbols=1',
45           '-nsim', TEST_BOARD_NSIM_ARGS,
46           '-OKN', RC_KERNEL_ELF
47          ]
48    }]
49
50TEST_NSIM_MULTICORE_CASES = [['--cores=2', '--nsim_args=' + TEST_NSIM_ARGS]]
51TEST_NSIM_CORE1 = [TEST_DRIVER_CMD, '-pset=1', '-psetname=core0',
52              '-nooptions', '-nogoifmain', '-toggle=include_local_symbols=1',
53              '-nsim', TEST_BOARD_NSIM_ARGS, RC_KERNEL_ELF]
54TEST_NSIM_CORE2 = [TEST_DRIVER_CMD, '-pset=2', '-psetname=core1',
55              '-prop=download=2', '-nooptions', '-nogoifmain',
56              '-toggle=include_local_symbols=1',
57              '-nsim', TEST_BOARD_NSIM_ARGS, RC_KERNEL_ELF]
58TEST_NSIM_CORES_LAUNCH = [TEST_DRIVER_CMD, '-multifiles=core0,core1',
59              '-run', '-cl']
60
61# mdb-hw
62TEST_HW_FLASH_CASES_NO_HOSTLINK = [
63    {
64        'i': ['--jtag=digilent', '--cores=1'],
65        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
66           '-toggle=include_local_symbols=1',
67           '-digilent',
68            '-run', '-cmd=-nowaitq run', '-cmd=quit', '-cl', RC_KERNEL_ELF]
69    }, {
70        'i': ['--jtag=digilent', '--cores=1', '--dig-device=test'],
71        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
72           '-toggle=include_local_symbols=1',
73           '-digilent', '-prop=dig_device=test',
74           '-run', '-cmd=-nowaitq run', '-cmd=quit', '-cl', RC_KERNEL_ELF]
75    }]
76
77TEST_HW_FLASH_CASES_HOSTLINK = [
78    {
79        'i': ['--jtag=digilent', '--cores=1'],
80        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
81           '-toggle=include_local_symbols=1',
82           '-digilent', '-run', '-cl', RC_KERNEL_ELF]
83    }, {
84        'i': ['--jtag=digilent', '--cores=1', '--dig-device=test'],
85        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
86           '-toggle=include_local_symbols=1',
87           '-digilent', '-prop=dig_device=test', '-run', '-cl', RC_KERNEL_ELF]
88    }]
89
90TEST_HW_FLASH_CASES_ERR = [
91    {
92        'i': ['--jtag=test_debug', '--cores=1'],
93        'e': "unsupported jtag adapter test_debug"
94    },{
95        'i': ['--jtag=digilent', '--cores=13'],
96        'e': "unsupported cores 13"
97    }]
98
99TEST_HW_DEBUG_CASES = [
100    {
101        'i': ['--jtag=digilent', '--cores=1'],
102        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
103               '-toggle=include_local_symbols=1',
104               '-digilent',
105               '-OKN', RC_KERNEL_ELF]
106    }, {
107        'i': ['--jtag=digilent', '--cores=1', '--dig-device=test'],
108        'o': [TEST_DRIVER_CMD, '-nooptions', '-nogoifmain',
109               '-toggle=include_local_symbols=1',
110               '-digilent', '-prop=dig_device=test',
111               '-OKN', RC_KERNEL_ELF]
112    }]
113
114TEST_HW_DEBUG_CASES_ERR = [
115    {
116        'i': ['--jtag=test_debug', '--cores=1'],
117        'e': "unsupported jtag adapter test_debug"
118    }, {
119        'i': ['--jtag=digilent', '--cores=13'],
120        'e': "unsupported cores 13"
121    }]
122
123TEST_HW_MULTICORE_CASES = [['--jtag=digilent', '--cores=2']]
124TEST_HW_CORE1 = [TEST_DRIVER_CMD, '-pset=1', '-psetname=core0',
125              '-nooptions', '-nogoifmain', '-toggle=include_local_symbols=1',
126              '-digilent', RC_KERNEL_ELF]
127TEST_HW_CORE2 = [TEST_DRIVER_CMD, '-pset=2', '-psetname=core1',
128              '-prop=download=2', '-nooptions', '-nogoifmain',
129              '-toggle=include_local_symbols=1',
130              '-digilent', RC_KERNEL_ELF]
131TEST_HW_CORES_LAUNCH_NO_HOSTLINK = [TEST_DRIVER_CMD, '-multifiles=core1,core0', '-run',
132              '-cmd=-nowaitq run', '-cmd=quit', '-cl']
133TEST_HW_CORES_LAUNCH_HOSTLINK = [TEST_DRIVER_CMD, '-multifiles=core1,core0', '-run', '-cl']
134
135
136def adjust_runner_config(runner_config, tmpdir, dotconfig):
137    # Adjust a RunnerConfig object, 'runner_config', by
138    # replacing its build directory with 'tmpdir' after writing
139    # the contents of 'dotconfig' to tmpdir/zephyr/.config.
140
141    zephyr = tmpdir / 'zephyr'
142    zephyr.mkdir()
143    with open(zephyr / '.config', 'w') as f:
144        f.write(dotconfig)
145
146    print("" + fspath(tmpdir))
147    return runner_config._replace(build_dir=fspath(tmpdir))
148
149#
150# Fixtures
151#
152
153def mdb(runner_config, tmpdir, mdb_runner):
154    '''MdbBinaryRunner from constructor kwargs or command line parameters'''
155    # This factory takes either a dict of kwargs to pass to the
156    # constructor, or a list of command-line arguments to parse and
157    # use with the create() method.
158    def _factory(args):
159        # Ensure kernel binaries exist (as empty files, so commands
160        # which use them must be patched out).
161        tmpdir.ensure(RC_KERNEL_ELF)
162        tmpdir.chdir()
163
164        if isinstance(args, dict):
165            return mdb_runner(runner_config, TEST_TARGET, **args)
166        elif isinstance(args, list):
167            parser = argparse.ArgumentParser(allow_abbrev=False)
168            mdb_runner.add_parser(parser)
169            arg_namespace = parser.parse_args(args)
170            return mdb_runner.create(runner_config, arg_namespace)
171
172    return _factory
173
174@pytest.fixture
175def mdb_nsim(runner_config, tmpdir):
176    return mdb(runner_config, tmpdir, MdbNsimBinaryRunner)
177
178@pytest.fixture
179def mdb_hw_no_hl(runner_config, tmpdir):
180    runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_NO_HOSTLINK)
181    return mdb(runner_config, tmpdir, MdbHwBinaryRunner)
182
183@pytest.fixture
184def mdb_hw_hl(runner_config, tmpdir):
185    runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_HOSTLINK)
186    return mdb(runner_config, tmpdir, MdbHwBinaryRunner)
187
188#
189# Helpers
190#
191
192def require_patch(program):
193    assert program == TEST_DRIVER_CMD
194
195#
196# Test cases for runners created by constructor.
197#
198
199# mdb-nsim test cases
200@pytest.mark.parametrize('test_case', TEST_NSIM_FLASH_CASES)
201@patch('runners.mdb.MdbNsimBinaryRunner.call')
202@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
203def test_flash_nsim(require, cc, test_case, mdb_nsim):
204    mdb_nsim(test_case['i']).run('flash')
205    assert require.called
206    cc.assert_called_once_with(test_case['o'], cwd=RC_BUILD_DIR)
207
208@pytest.mark.parametrize('test_case', TEST_NSIM_DEBUG_CASES)
209@patch('runners.mdb.MdbNsimBinaryRunner.call')
210@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
211def test_debug_nsim(require, pii, test_case, mdb_nsim):
212    mdb_nsim(test_case['i']).run('debug')
213    assert require.called
214    pii.assert_called_once_with(test_case['o'], cwd=RC_BUILD_DIR)
215
216@pytest.mark.parametrize('test_case', TEST_NSIM_MULTICORE_CASES)
217@patch('runners.mdb.MdbNsimBinaryRunner.check_call')
218@patch('runners.mdb.MdbNsimBinaryRunner.call')
219@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
220def test_multicores_nsim(require, pii, cc, test_case, mdb_nsim):
221    mdb_nsim(test_case).run('flash')
222    assert require.called
223    cc_calls = [call(TEST_NSIM_CORE1, cwd=RC_BUILD_DIR), call(TEST_NSIM_CORE2, cwd=RC_BUILD_DIR)]
224    cc.assert_has_calls(cc_calls)
225    pii.assert_called_once_with(TEST_NSIM_CORES_LAUNCH, cwd=RC_BUILD_DIR)
226
227
228# mdb-hw test cases
229@pytest.mark.parametrize('test_case', TEST_HW_FLASH_CASES_NO_HOSTLINK)
230@patch('runners.mdb.MdbHwBinaryRunner.call')
231@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
232def test_flash_hw_no_hl(require, cc, test_case, mdb_hw_no_hl, tmpdir):
233    mdb_hw_no_hl(test_case['i']).run('flash')
234    assert require.called
235    cc.assert_called_once_with(test_case['o'], cwd=tmpdir)
236
237@pytest.mark.parametrize('test_case', TEST_HW_FLASH_CASES_HOSTLINK)
238@patch('runners.mdb.MdbHwBinaryRunner.call')
239@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
240def test_flash_hw_hl(require, cc, test_case, mdb_hw_hl, tmpdir):
241    mdb_hw_hl(test_case['i']).run('flash')
242    assert require.called
243    cc.assert_called_once_with(test_case['o'], cwd=tmpdir)
244
245@pytest.mark.parametrize('test_case', TEST_HW_FLASH_CASES_ERR)
246@patch('runners.mdb.MdbHwBinaryRunner.call')
247@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
248def test_flash_hw_err(require, cc, test_case, mdb_hw_no_hl):
249    with pytest.raises(ValueError) as rinfo:
250        mdb_hw_no_hl(test_case['i']).run('flash')
251
252    assert str(rinfo.value) == test_case['e']
253
254@pytest.mark.parametrize('test_case', TEST_HW_DEBUG_CASES)
255@patch('runners.mdb.MdbHwBinaryRunner.call')
256@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
257def test_debug_hw(require, pii, test_case, mdb_hw_no_hl, tmpdir):
258    mdb_hw_no_hl(test_case['i']).run('debug')
259    assert require.called
260    pii.assert_called_once_with(test_case['o'], cwd=tmpdir)
261
262@pytest.mark.parametrize('test_case', TEST_HW_DEBUG_CASES)
263@patch('runners.mdb.MdbHwBinaryRunner.call')
264@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
265def test_debug_hw_hl(require, pii, test_case, mdb_hw_hl, tmpdir):
266    mdb_hw_hl(test_case['i']).run('debug')
267    assert require.called
268    pii.assert_called_once_with(test_case['o'], cwd=tmpdir)
269
270@pytest.mark.parametrize('test_case', TEST_HW_DEBUG_CASES_ERR)
271@patch('runners.mdb.MdbHwBinaryRunner.call')
272@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
273def test_debug_hw_err(require, pii, test_case, mdb_hw_no_hl):
274    with pytest.raises(ValueError) as rinfo:
275        mdb_hw_no_hl(test_case['i']).run('debug')
276
277    assert str(rinfo.value) == test_case['e']
278
279@pytest.mark.parametrize('test_case', TEST_HW_MULTICORE_CASES)
280@patch('runners.mdb.MdbHwBinaryRunner.check_call')
281@patch('runners.mdb.MdbHwBinaryRunner.call')
282@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
283def test_multicores_hw_no_hl(require, pii, cc, test_case, mdb_hw_no_hl, tmpdir):
284    mdb_hw_no_hl(test_case).run('flash')
285    assert require.called
286    cc_calls = [call(TEST_HW_CORE1, cwd=tmpdir), call(TEST_HW_CORE2, cwd=tmpdir)]
287    cc.assert_has_calls(cc_calls)
288    pii.assert_called_once_with(TEST_HW_CORES_LAUNCH_NO_HOSTLINK, cwd=tmpdir)
289
290@pytest.mark.parametrize('test_case', TEST_HW_MULTICORE_CASES)
291@patch('runners.mdb.MdbHwBinaryRunner.check_call')
292@patch('runners.mdb.MdbHwBinaryRunner.call')
293@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
294def test_multicores_hw_hl(require, pii, cc, test_case, mdb_hw_hl, tmpdir):
295    mdb_hw_hl(test_case).run('flash')
296    assert require.called
297    cc_calls = [call(TEST_HW_CORE1, cwd=tmpdir), call(TEST_HW_CORE2, cwd=tmpdir)]
298    cc.assert_has_calls(cc_calls)
299    pii.assert_called_once_with(TEST_HW_CORES_LAUNCH_HOSTLINK, cwd=tmpdir)
300