mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
ci(tools): Avoiding full rebuilds where not needed to improve performance
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging
|
||||
@@ -8,7 +8,10 @@ import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from test_build_system_helpers import EnvDict, IdfPyFunc, append_to_file, replace_in_file
|
||||
from test_build_system_helpers import EnvDict
|
||||
from test_build_system_helpers import IdfPyFunc
|
||||
from test_build_system_helpers import append_to_file
|
||||
from test_build_system_helpers import replace_in_file
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('test_app_copy')
|
||||
@@ -30,15 +33,21 @@ def test_partition_nearly_full_warning(idf_py: IdfPyFunc, test_app_copy: Path, d
|
||||
logging.info('Warning is given if smallest partition is nearly full')
|
||||
ret = idf_py('build')
|
||||
# Build a first time to get the binary size and to check that no warning is issued.
|
||||
assert 'partition is nearly full' not in ret.stdout, 'Warning for nearly full smallest partition was given when the condition is not fulfilled'
|
||||
assert 'partition is nearly full' not in ret.stdout, (
|
||||
'Warning for nearly full smallest partition was given when the condition is not fulfilled'
|
||||
)
|
||||
# Get the size of the binary, in KB. Convert it to next multiple of 4.
|
||||
# The goal is to create an app partition which is slightly bigger than the binary itself
|
||||
updated_file_size = int((os.stat(test_app_copy / 'build' / 'build_test_app.bin').st_size + 4095) / 4096) * 4
|
||||
idf_path = Path(default_idf_env['IDF_PATH'])
|
||||
shutil.copy2(idf_path / 'components' / 'partition_table' / 'partitions_singleapp.csv', test_app_copy / 'partitions.csv')
|
||||
replace_in_file(test_app_copy / 'partitions.csv',
|
||||
'factory, app, factory, , 1M',
|
||||
f'factory, app, factory, , {updated_file_size}K')
|
||||
(test_app_copy / 'sdkconfig').write_text('\n'.join(['CONFIG_PARTITION_TABLE_CUSTOM=y', 'CONFIG_FREERTOS_SMP=n']))
|
||||
shutil.copy2(
|
||||
idf_path / 'components' / 'partition_table' / 'partitions_singleapp.csv', test_app_copy / 'partitions.csv'
|
||||
)
|
||||
replace_in_file(
|
||||
test_app_copy / 'partitions.csv',
|
||||
'factory, app, factory, , 1M',
|
||||
f'factory, app, factory, , {updated_file_size}K',
|
||||
)
|
||||
append_to_file(test_app_copy / 'sdkconfig', '\n'.join(['CONFIG_PARTITION_TABLE_CUSTOM=y', 'CONFIG_FREERTOS_SMP=n']))
|
||||
ret = idf_py('build', check=False)
|
||||
assert 'partition is nearly full' in ret.stdout
|
||||
|
||||
@@ -82,7 +82,7 @@ def test_spaces_bundle3(idf_copy: Path) -> None:
|
||||
def test_spaces_bundle4(dummy_: str, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||
logging.info(f'Running test spaces bundle 4 in {test_app_copy}')
|
||||
(test_app_copy / 'sdkconfig').write_text('CONFIG_APP_REPRODUCIBLE_BUILD=y')
|
||||
idf_py('build')
|
||||
idf_py('reconfigure')
|
||||
(test_app_copy / 'sdkconfig').unlink()
|
||||
|
||||
idf_py('set-target', 'esp32s2')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import json
|
||||
import os
|
||||
@@ -50,48 +50,54 @@ class TestWithoutExtensions(TestCase):
|
||||
|
||||
|
||||
class TestExtensions(TestWithoutExtensions):
|
||||
def test_extension_loading(self):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
# Create symlink once for all tests in this class
|
||||
# Handle race conditions with parallel test execution (pytest-xdist)
|
||||
try:
|
||||
os.symlink(extension_path, link_path)
|
||||
os.environ['IDF_EXTRA_ACTIONS_PATH'] = os.path.join(current_dir, 'extra_path')
|
||||
output = subprocess.check_output([sys.executable, idf_py_path, '--help'], env=os.environ).decode(
|
||||
'utf-8', 'ignore'
|
||||
)
|
||||
except FileExistsError:
|
||||
# Another worker already created it - that's fine
|
||||
pass
|
||||
os.environ['IDF_EXTRA_ACTIONS_PATH'] = os.path.join(current_dir, 'extra_path')
|
||||
|
||||
self.assertIn('--test-extension-option', output)
|
||||
self.assertIn('test_subcommand', output)
|
||||
self.assertIn('--some-extension-option', output)
|
||||
self.assertIn('extra_subcommand', output)
|
||||
finally:
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
# Clean up symlink after all tests complete
|
||||
# Use try/except to handle race conditions with parallel execution
|
||||
try:
|
||||
os.remove(link_path)
|
||||
except FileNotFoundError:
|
||||
# Another worker already removed it - that's fine
|
||||
pass
|
||||
super().tearDownClass()
|
||||
|
||||
def test_extension_loading(self):
|
||||
output = subprocess.check_output([sys.executable, idf_py_path, '--help'], env=os.environ).decode(
|
||||
'utf-8', 'ignore'
|
||||
)
|
||||
self.assertIn('--test-extension-option', output)
|
||||
self.assertIn('test_subcommand', output)
|
||||
self.assertIn('--some-extension-option', output)
|
||||
self.assertIn('extra_subcommand', output)
|
||||
|
||||
def test_extension_execution(self):
|
||||
try:
|
||||
os.symlink(extension_path, link_path)
|
||||
os.environ['IDF_EXTRA_ACTIONS_PATH'] = ';'.join([os.path.join(current_dir, 'extra_path')])
|
||||
output = subprocess.check_output(
|
||||
[sys.executable, idf_py_path, '--some-extension-option=awesome', 'test_subcommand', 'extra_subcommand'],
|
||||
env=os.environ,
|
||||
).decode('utf-8', 'ignore')
|
||||
self.assertIn('!!! From some global callback: awesome', output)
|
||||
self.assertIn('!!! From some subcommand', output)
|
||||
self.assertIn('!!! From test global callback: test', output)
|
||||
self.assertIn('!!! From some subcommand', output)
|
||||
finally:
|
||||
os.remove(link_path)
|
||||
output = subprocess.check_output(
|
||||
[sys.executable, idf_py_path, '--some-extension-option=awesome', 'test_subcommand', 'extra_subcommand'],
|
||||
env=os.environ,
|
||||
).decode('utf-8', 'ignore')
|
||||
self.assertIn('!!! From some global callback: awesome', output)
|
||||
self.assertIn('!!! From some subcommand', output)
|
||||
self.assertIn('!!! From test global callback: test', output)
|
||||
self.assertIn('!!! From some subcommand', output)
|
||||
|
||||
def test_hidden_commands(self):
|
||||
try:
|
||||
os.symlink(extension_path, link_path)
|
||||
os.environ['IDF_EXTRA_ACTIONS_PATH'] = ';'.join([os.path.join(current_dir, 'extra_path')])
|
||||
output = subprocess.check_output([sys.executable, idf_py_path, '--help'], env=os.environ).decode(
|
||||
'utf-8', 'ignore'
|
||||
)
|
||||
self.assertIn('test_subcommand', output)
|
||||
self.assertNotIn('hidden_one', output)
|
||||
|
||||
finally:
|
||||
os.remove(link_path)
|
||||
output = subprocess.check_output([sys.executable, idf_py_path, '--help'], env=os.environ).decode(
|
||||
'utf-8', 'ignore'
|
||||
)
|
||||
self.assertIn('test_subcommand', output)
|
||||
self.assertNotIn('hidden_one', output)
|
||||
|
||||
|
||||
class TestDependencyManagement(TestWithoutExtensions):
|
||||
|
||||
Reference in New Issue
Block a user