mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat: Add unit tests for new wrapper commands
This commit is contained in:
parent
a648a95660
commit
b286105d5f
@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn
|
||||
write-changes = true
|
||||
|
@ -9,7 +9,6 @@ from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
||||
import click
|
||||
from idf_py_actions.global_options import global_options
|
||||
@ -405,7 +404,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
if version:
|
||||
generate_signing_key_args += ['--version', version]
|
||||
if scheme:
|
||||
generate_signing_key_args += ['--scheme', '2']
|
||||
generate_signing_key_args += ['--scheme', scheme]
|
||||
if extra_args['keyfile']:
|
||||
generate_signing_key_args += [extra_args['keyfile']]
|
||||
RunTool('espsecure', generate_signing_key_args, args.build_dir)()
|
||||
@ -440,10 +439,13 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
|
||||
def _parse_efuse_args(ctx: click.core.Context, args: PropertyDict, extra_args: Dict) -> List:
|
||||
efuse_args = []
|
||||
efuse_args += ['-p', args.port or get_default_serial_port()]
|
||||
if args.baud:
|
||||
efuse_args += ['-b', str(args.baud)]
|
||||
if args.port:
|
||||
efuse_args += ['-p', args.port]
|
||||
elif not args.port and not extra_args['virt']: # if --virt, no port will be found and it would cause error
|
||||
efuse_args += ['-p', get_default_serial_port()]
|
||||
efuse_args += ['--chip', _get_project_desc(ctx, args)['target']]
|
||||
if extra_args['virt']:
|
||||
efuse_args += ['--virt']
|
||||
if extra_args['before']:
|
||||
efuse_args += ['--before', extra_args['before'].replace('-', '_')]
|
||||
if extra_args['debug']:
|
||||
@ -470,8 +472,8 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
burn_key_args += ['--force-write-always']
|
||||
if extra_args['show_sensitive_info']:
|
||||
burn_key_args += ['--show-sensitive-info']
|
||||
if extra_args['image']:
|
||||
burn_key_args.append(extra_args['image'])
|
||||
if extra_args['efuse_positional_args']:
|
||||
burn_key_args += extra_args['efuse_positional_args']
|
||||
RunTool('espefuse.py', burn_key_args, args.project_dir, build_dir=args.build_dir)()
|
||||
|
||||
def efuse_dump(action: str, ctx: click.core.Context, args: PropertyDict, file_name: str, **extra_args: Dict) -> None:
|
||||
@ -490,14 +492,14 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
read_protect_args += list(extra_args['efuse_positional_args'])
|
||||
RunTool('espefuse', read_protect_args, args.build_dir)()
|
||||
|
||||
def efuse_summary(action: str, ctx: click.core.Context, args: PropertyDict, format: str, **extra_args: Tuple) -> None:
|
||||
def efuse_summary(action: str, ctx: click.core.Context, args: PropertyDict, format: str, **extra_args: Dict) -> None:
|
||||
ensure_build_directory(args, ctx.info_name)
|
||||
summary_args = [PYTHON, '-m' 'espefuse', 'summary']
|
||||
summary_args += _parse_efuse_args(ctx, args, extra_args)
|
||||
if format:
|
||||
summary_args += ['--format', format.replace('-', '_')]
|
||||
if extra_args['efuses']:
|
||||
summary_args += extra_args['efuse_name']
|
||||
summary_args += [f'--format={format.replace("-", "_")}']
|
||||
if extra_args['efuse_name']:
|
||||
summary_args += [str(extra_args['efuse_name'])]
|
||||
RunTool('espefuse', summary_args, args.build_dir)()
|
||||
|
||||
def efuse_write_protect(action: str, ctx: click.core.Context, args: PropertyDict, **extra_args: Dict) -> None:
|
||||
@ -524,7 +526,13 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
}
|
||||
]
|
||||
|
||||
EFUSE_OPTS = BAUD_AND_PORT + [
|
||||
EFUSE_OPTS = [PORT] + [
|
||||
{
|
||||
'names': ['--virt'],
|
||||
'is_flag': True,
|
||||
'hidden': True,
|
||||
'help': 'For host tests, the tool will work in the virtual mode (without connecting to a chip).',
|
||||
},
|
||||
{
|
||||
'names': ['--before'],
|
||||
'help': 'What to do before connecting to the chip.',
|
||||
@ -802,6 +810,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
'options': EFUSE_OPTS + [
|
||||
{
|
||||
'names': ['--no-protect-key'],
|
||||
'is_flag': True,
|
||||
'help': (
|
||||
'Disable default read- and write-protecting of the key.'
|
||||
'If this option is not set, once the key is flashed it cannot be read back or changed.'
|
||||
@ -809,6 +818,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
},
|
||||
{
|
||||
'names': ['--force-write-always'],
|
||||
'is_flag': True,
|
||||
'help': (
|
||||
"Write the eFuse even if it looks like it's already been written, or is write protected."
|
||||
"Note that this option can't disable write protection, or clear any bit which has already been set."
|
||||
@ -816,6 +826,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
},
|
||||
{
|
||||
'names': ['--show-sensitive-info'],
|
||||
'is_flag': True,
|
||||
'help': (
|
||||
'Show data to be burned (may expose sensitive data). Enabled if --debug is used.'
|
||||
),
|
||||
@ -823,8 +834,8 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
],
|
||||
'arguments': [
|
||||
{
|
||||
'names': ['image'],
|
||||
'nargs': 1,
|
||||
'names': ['efuse-positional-args'],
|
||||
'nargs': -1,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -866,6 +877,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
||||
{
|
||||
'names': ['efuse-name'],
|
||||
'nargs': 1,
|
||||
'required': False,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -360,5 +360,182 @@ class TestFileArgumentExpansion(TestCase):
|
||||
self.assertIn('(expansion of @args_non_existent) could not be opened', cm.exception.output.decode('utf-8', 'ignore'))
|
||||
|
||||
|
||||
class TestWrapperCommands(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sample_project_dir = os.path.join(current_dir, '..', 'test_build_system', 'build_test_app')
|
||||
os.chdir(cls.sample_project_dir)
|
||||
super().setUpClass()
|
||||
|
||||
def call_command(self, command: List[str]) -> str:
|
||||
try:
|
||||
output = subprocess.check_output(
|
||||
command,
|
||||
env=os.environ,
|
||||
stderr=subprocess.STDOUT).decode('utf-8', 'ignore')
|
||||
return output
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.fail(f'Process should have exited normally, but it exited with a return code of {e.returncode}')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
subprocess.run([sys.executable, idf_py_path, 'fullclean'], stdout=subprocess.DEVNULL)
|
||||
os.chdir(current_dir)
|
||||
super().tearDownClass()
|
||||
|
||||
|
||||
class TestEFuseCommands(TestWrapperCommands):
|
||||
"""
|
||||
Test if wrapper commands for espefuse.py are working as expected.
|
||||
The goal is NOT to test the functionality of espefuse.py, but to test if the wrapper commands are working as expected.
|
||||
"""
|
||||
|
||||
def test_efuse_summary(self):
|
||||
summary_command = [sys.executable, idf_py_path, 'efuse-summary', '--virt']
|
||||
output = self.call_command(summary_command)
|
||||
self.assertIn('EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)', output)
|
||||
|
||||
output = self.call_command(summary_command + ['--format','summary'])
|
||||
self.assertIn('00:00:00:00:00:00', output)
|
||||
self.assertIn('MAC address', output)
|
||||
|
||||
output = self.call_command(summary_command + ['--format','value-only', 'WR_DIS'])
|
||||
self.assertIn('0', output)
|
||||
|
||||
def test_efuse_burn(self):
|
||||
burn_command = [sys.executable, idf_py_path, 'efuse-burn', '--virt', '--do-not-confirm']
|
||||
output = self.call_command(burn_command + ['WR_DIS', '1'])
|
||||
self.assertIn('\'WR_DIS\' (Efuse write disable mask) 0x0000 -> 0x0001', output)
|
||||
self.assertIn('Successful', output)
|
||||
|
||||
output = self.call_command(burn_command + ['WR_DIS', '1', 'RD_DIS', '1'])
|
||||
self.assertIn('WR_DIS', output)
|
||||
self.assertIn('RD_DIS', output)
|
||||
self.assertIn('Successful', output)
|
||||
|
||||
def test_efuse_burn_key(self):
|
||||
key_name = 'efuse_test_key.bin'
|
||||
subprocess.run([sys.executable, idf_py_path, 'secure-generate-flash-encryption-key', os.path.join(current_dir, key_name)], stdout=subprocess.DEVNULL)
|
||||
burn_key_command = [sys.executable, idf_py_path, 'efuse-burn-key', '--virt', '--do-not-confirm']
|
||||
output = self.call_command(burn_key_command + ['--show-sensitive-info', 'secure_boot_v1', os.path.join(current_dir, key_name)])
|
||||
self.assertIn('Burn keys to blocks:', output)
|
||||
self.assertIn('Successful', output)
|
||||
|
||||
def test_efuse_dump(self):
|
||||
dump_command = [sys.executable, idf_py_path, 'efuse-dump', '--virt']
|
||||
output = self.call_command(dump_command)
|
||||
self.assertIn('BLOCK0', output)
|
||||
self.assertIn('BLOCK1', output)
|
||||
self.assertIn('BLOCK2', output)
|
||||
self.assertIn('BLOCK3', output)
|
||||
self.assertIn('read_regs', output)
|
||||
|
||||
def test_efuse_read_protect(self):
|
||||
read_protect_command = [sys.executable, idf_py_path, 'efuse-read-protect', '--virt', '--do-not-confirm']
|
||||
output = self.call_command(read_protect_command + ['MAC_VERSION'])
|
||||
self.assertIn('MAC_VERSION', output)
|
||||
self.assertIn('Successful', output)
|
||||
|
||||
def test_efuse_write_protect(self):
|
||||
write_protect_command = [sys.executable, idf_py_path, 'efuse-write-protect', '--virt', '--do-not-confirm']
|
||||
output = self.call_command(write_protect_command + ['WR_DIS'])
|
||||
self.assertIn('WR_DIS', output)
|
||||
self.assertIn('Successful', output)
|
||||
|
||||
|
||||
class TestSecureCommands(TestWrapperCommands):
|
||||
"""
|
||||
Test if wrapper commands for espsecure.py are working as expected.
|
||||
The goal is NOT to test the functionality of espsecure.py, but to test if the wrapper commands are working as expected.
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
subprocess.run([sys.executable, idf_py_path, 'build'], stdout=subprocess.DEVNULL)
|
||||
cls.flash_encryption_key = 'test_key.bin'
|
||||
cls.signing_key = 'test_signing_key.pem'
|
||||
|
||||
def secure_generate_flash_encryption_key(self):
|
||||
generate_key_command = [sys.executable, idf_py_path, 'secure-generate-flash-encryption-key', self.flash_encryption_key]
|
||||
output = self.call_command(generate_key_command)
|
||||
self.assertIn(f'Writing 256 random bits to key file {self.flash_encryption_key}', output)
|
||||
|
||||
def secure_encrypt_flash_data(self):
|
||||
self.secure_generate_flash_encryption_key()
|
||||
encrypt_command = [sys.executable,
|
||||
idf_py_path,
|
||||
'secure-encrypt-flash-data',
|
||||
'--aes-xts',
|
||||
'--keyfile',
|
||||
f'{self.flash_encryption_key}',
|
||||
'--address',
|
||||
'0x1000',
|
||||
'--output',
|
||||
'bootloader-enc.bin',
|
||||
'bootloader/bootloader.bin']
|
||||
output = self.call_command(encrypt_command)
|
||||
self.assertIn('Using 256-bit key', output)
|
||||
self.assertIn('Done', output)
|
||||
|
||||
def test_secure_decrypt_flash_data(self):
|
||||
self.secure_encrypt_flash_data()
|
||||
decrypt_command = [sys.executable,
|
||||
idf_py_path,
|
||||
'secure-decrypt-flash-data',
|
||||
'--aes-xts',
|
||||
'--keyfile',
|
||||
f'{self.flash_encryption_key}',
|
||||
'--address',
|
||||
'0x1000',
|
||||
'--output',
|
||||
'bootloader-dec.bin',
|
||||
'bootloader-enc.bin']
|
||||
output = self.call_command(decrypt_command)
|
||||
self.assertIn('Using 256-bit key', output)
|
||||
self.assertIn('Done', output)
|
||||
|
||||
def secure_generate_signing_key(self):
|
||||
generate_key_command = [sys.executable,
|
||||
idf_py_path,
|
||||
'secure-generate-signing-key',
|
||||
'--version',
|
||||
'2',
|
||||
'--scheme',
|
||||
'rsa3072',
|
||||
self.signing_key]
|
||||
output = self.call_command(generate_key_command)
|
||||
self.assertIn(f'RSA 3072 private key in PEM format written to {self.signing_key}', output)
|
||||
self.assertIn('Done', output)
|
||||
|
||||
def secure_sign_data(self):
|
||||
self.secure_generate_signing_key()
|
||||
sign_command = [sys.executable,
|
||||
idf_py_path,
|
||||
'secure-sign-data',
|
||||
'--version',
|
||||
'2',
|
||||
'--keyfile',
|
||||
self.signing_key,
|
||||
'--output',
|
||||
'bootloader-signed.bin',
|
||||
'bootloader/bootloader.bin']
|
||||
output = self.call_command(sign_command)
|
||||
self.assertIn('Signed', output)
|
||||
|
||||
|
||||
class TestMergeBinCommands(TestWrapperCommands):
|
||||
"""
|
||||
Test if merge-bin command is invoked as expected.
|
||||
This test is not testing the functionality of esptool.py merge_bin command, but the invocation of the command from idf.py.
|
||||
"""
|
||||
|
||||
def test_merge_bin(self):
|
||||
merge_bin_command = [sys.executable, idf_py_path, 'merge-bin']
|
||||
merged_binary_name = 'test-merge-binary.bin'
|
||||
output = self.call_command(merge_bin_command + ['--output', merged_binary_name])
|
||||
self.assertIn(f'file {merged_binary_name}, ready to flash to offset 0x0', output)
|
||||
self.assertIn(f'Merged binary {merged_binary_name} will be created in the build directory...', output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user