mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 03:34:32 +02:00
ci(tools): add tests for component_requirements.py hints module
Following tests were added. 1. Test for missing header directory in component's INCLUDE_DIRS 2. Test for missing dependency in component's PRIV_REQUIRES 3. Test for missing dependency in component's REQUIRES 4. Test for dependency in PRIV_REQUIRES which should be in REQUIRES Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
from subprocess import run
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
@@ -31,5 +34,79 @@ class TestHintsMassages(unittest.TestCase):
|
|||||||
self.assertEqual(generated_hint, hint)
|
self.assertEqual(generated_hint, hint)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHintModuleComponentRequirements(unittest.TestCase):
|
||||||
|
def run_cmd(self, cmd: List[str]) -> str:
|
||||||
|
# Simple helper to run command and return it's stdout.
|
||||||
|
proc = run(cmd, capture_output=True, cwd=str(self.projectdir), text=True)
|
||||||
|
return proc.stdout + proc.stderr
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
# Set up a dummy project in tmp directory with main and component1 component.
|
||||||
|
# The main component includes component1.h from component1, but the header dir is
|
||||||
|
# not added in INCLUDE_DIRS and main doesn't have REQUIRES for component1.
|
||||||
|
self.tmpdir = tempfile.TemporaryDirectory()
|
||||||
|
self.tmpdirpath = Path(self.tmpdir.name)
|
||||||
|
|
||||||
|
self.projectdir = self.tmpdirpath / 'project'
|
||||||
|
self.projectdir.mkdir(parents=True)
|
||||||
|
(self.projectdir / 'CMakeLists.txt').write_text((
|
||||||
|
'cmake_minimum_required(VERSION 3.16)\n'
|
||||||
|
'include($ENV{IDF_PATH}/tools/cmake/project.cmake)\n'
|
||||||
|
'project(foo)'))
|
||||||
|
|
||||||
|
maindir = self.projectdir / 'main'
|
||||||
|
maindir.mkdir()
|
||||||
|
(maindir / 'CMakeLists.txt').write_text('idf_component_register(SRCS "foo.c" REQUIRES esp_timer)')
|
||||||
|
(maindir / 'foo.h').write_text('#include "component1.h"')
|
||||||
|
(maindir / 'foo.c').write_text('#include "foo.h"\nvoid app_main(){}')
|
||||||
|
|
||||||
|
component1dir = self.projectdir / 'components' / 'component1'
|
||||||
|
component1dir.mkdir(parents=True)
|
||||||
|
(component1dir / 'CMakeLists.txt').write_text('idf_component_register()')
|
||||||
|
(component1dir / 'component1.h').touch()
|
||||||
|
|
||||||
|
def test_component_requirements(self) -> None:
|
||||||
|
# The main component uses component1.h, but this header is not in component1 public
|
||||||
|
# interface. Hints should suggest that component1.h should be added into INCLUDE_DIRS
|
||||||
|
# of component1.
|
||||||
|
output = self.run_cmd(['idf.py', 'app'])
|
||||||
|
self.assertIn('Missing "component1.h" file name found in the following component(s): component1(', output)
|
||||||
|
|
||||||
|
# Based on previous hint the component1.h is added to INCLUDE_DIRS, but main still doesn't
|
||||||
|
# have dependency on compoment1. Hints should suggest to add component1 into main component
|
||||||
|
# PRIV_REQUIRES, because foo.h is not in main public interface.
|
||||||
|
self.run_cmd(['idf.py', 'fullclean'])
|
||||||
|
component1cmake = self.projectdir / 'components' / 'component1' / 'CMakeLists.txt'
|
||||||
|
component1cmake.write_text('idf_component_register(INCLUDE_DIRS ".")')
|
||||||
|
output = self.run_cmd(['idf.py', 'app'])
|
||||||
|
self.assertIn('To fix this, add component1 to PRIV_REQUIRES list of idf_component_register call', output)
|
||||||
|
|
||||||
|
# Add foo.h into main public interface. Now the hint should suggest to use
|
||||||
|
# REQUIRES instead of PRIV_REQUIRES.
|
||||||
|
self.run_cmd(['idf.py', 'fullclean'])
|
||||||
|
maincmake = self.projectdir / 'main' / 'CMakeLists.txt'
|
||||||
|
maincmake.write_text(('idf_component_register(SRCS "foo.c" '
|
||||||
|
'REQUIRES esp_timer '
|
||||||
|
'INCLUDE_DIRS ".")'))
|
||||||
|
output = self.run_cmd(['idf.py', 'app'])
|
||||||
|
self.assertIn('To fix this, add component1 to REQUIRES list of idf_component_register call', output)
|
||||||
|
|
||||||
|
# Add component1 to REQUIRES as suggested by previous hint, but also
|
||||||
|
# add esp_psram as private req for component1 and add esp_psram.h
|
||||||
|
# to component1.h. New the hint should report that esp_psram should
|
||||||
|
# be moved from PRIV_REQUIRES to REQUIRES for component1.
|
||||||
|
self.run_cmd(['idf.py', 'fullclean'])
|
||||||
|
maincmake.write_text(('idf_component_register(SRCS "foo.c" '
|
||||||
|
'REQUIRES esp_timer component1 '
|
||||||
|
'INCLUDE_DIRS ".")'))
|
||||||
|
(self.projectdir / 'components' / 'component1' / 'component1.h').write_text('#include "esp_psram.h"')
|
||||||
|
component1cmake.write_text('idf_component_register(INCLUDE_DIRS "." PRIV_REQUIRES esp_psram)')
|
||||||
|
output = self.run_cmd(['idf.py', 'app'])
|
||||||
|
self.assertIn('To fix this, move esp_psram from PRIV_REQUIRES into REQUIRES', output)
|
||||||
|
|
||||||
|
def tearDown(self) -> None:
|
||||||
|
self.tmpdir.cleanup()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user