blob: 2cb656f12bf7277c45d9a817d433c2c77eb031e5 [file] [edit]
# Copyright 2025 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tests for cmake_converter_common.py."""
from pathlib import Path
from typing import Any
import unittest
import cmake_converter_common as common
class CmakeConverterCommonTest(unittest.TestCase):
"""Tests for cmake_converter_common.py."""
def test_translate_relative_path(self):
output = common.translate_relative_path(
Path('/a/b/c'), Path('/a'), Path('/x')
)
self.assertEqual(output, Path('/x/b/c'))
with self.assertRaises(ValueError) as e:
common.translate_relative_path(
Path('/xxx/b/c'), Path('/a'), Path('/x')
)
self.assertEqual(str(e.exception), '/xxx/b/c is not inside /a')
def test_parse_if_block_ast_node_simple_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'CONFIG_FEATURE',
'body': [],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(len(rules), 1)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' "@zephyr_kconfig//:CONFIG_FEATURE=true":'
' [":target_config_feature_deps"],'
),
' "//conditions:default": [],',
' })',
]),
)
def test_parse_if_block_ast_node_not_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'NOT CONFIG_FEATURE',
'body': [
{
'type': 'unconditional_source',
'srcs': ['no_feature.c'],
},
],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(len(rules), 1)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' "//conditions:default":'
' [":target_not_config_feature_deps"],'
),
' "@zephyr_kconfig//:CONFIG_FEATURE=true": [],',
' })',
]),
)
def test_parse_if_block_ast_node_or_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'CONFIG_A OR CONFIG_B',
'body': [
{'type': 'unconditional_source', 'srcs': ['feature.c']},
],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(
rules,
[
"""selects.config_setting_group(
name = "config_a_or_config_b",
match_any = ['@zephyr_kconfig//:CONFIG_A=true', '@zephyr_kconfig//:CONFIG_B=true'],
)""",
"""cc_library(
name = "target_config_a_or_config_b_deps",
)""",
],
)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' ":config_a_or_config_b":'
' [":target_config_a_or_config_b_deps"],'
),
' "//conditions:default": [],',
' })',
]),
)
def test_parse_if_block_ast_node_and_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'CONFIG_A AND CONFIG_B',
'body': [
{'type': 'unconditional_source', 'srcs': ['feature.c']},
],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(
rules,
[
"""selects.config_setting_group(
name = "config_a_and_config_b",
match_all = ['@zephyr_kconfig//:CONFIG_A=true', '@zephyr_kconfig//:CONFIG_B=true'],
)""",
"""cc_library(
name = "target_config_a_and_config_b_deps",
)""",
],
)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' ":config_a_and_config_b":'
' [":target_config_a_and_config_b_deps"],'
),
' "//conditions:default": [],',
' })',
]),
)
def test_parse_if_block_ast_node_or_not_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'CONFIG_A OR NOT CONFIG_B',
'body': [],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(
rules,
[
"""config_setting(
name = "not_config_b",
flag_values = {
"@zephyr_kconfig//:CONFIG_B": "false",
},
)""",
"""selects.config_setting_group(
name = "config_a_or_not_config_b",
match_any = ['@zephyr_kconfig//:CONFIG_A=true', ':not_config_b'],
)""",
"""cc_library(
name = "target_config_a_or_not_config_b_deps",
)""",
],
)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' ":config_a_or_not_config_b":'
' [":target_config_a_or_not_config_b_deps"],'
),
' "//conditions:default": [],',
' })',
]),
)
def test_parse_if_block_ast_node_and_not_condition(self):
def recursive_callback(
ast: list[dict[str, Any]],
target_name: str,
) -> list[str]:
return [f"""cc_library(
name = "{target_name}",
)"""]
node = {
'type': 'if_block',
'branches': [
{
'condition': 'CONFIG_A AND NOT CONFIG_B',
'body': [],
},
],
'else_body': None,
}
rules, deps_selects = common.parse_if_block_ast_node(
node, 'target', recursive_callback
)
self.assertEqual(
rules,
[
"""config_setting(
name = "not_config_b",
flag_values = {
"@zephyr_kconfig//:CONFIG_B": "false",
},
)""",
"""selects.config_setting_group(
name = "config_a_and_not_config_b",
match_all = ['@zephyr_kconfig//:CONFIG_A=true', ':not_config_b'],
)""",
"""cc_library(
name = "target_config_a_and_not_config_b_deps",
)""",
],
)
self.assertEqual(
deps_selects,
'\n'.join([
' + select({',
(
' ":config_a_and_not_config_b":'
' [":target_config_a_and_not_config_b_deps"],'
),
' "//conditions:default": [],',
' })',
]),
)
def test_process_zephyr_cmake_functions_uart_native(self):
output = common._process_zephyr_cmake_functions(
'zephyr_library_sources(uart_native_pty.c)'
)
self.assertEqual(
output,
{
'type': 'unconditional_source',
'srcs': ['uart_native_pty.c', 'uart_native_pty_bottom.c'],
},
)
output = common._process_zephyr_cmake_functions(
'zephyr_library_sources_ifdef(CONFIG_UART_NATIVE_TTY uart_native_tty.c)'
)
self.assertEqual(
output,
{
'type': 'conditional_source',
'config': 'CONFIG_UART_NATIVE_TTY',
'srcs': ['uart_native_tty.c', 'uart_native_tty_bottom.c'],
},
)
def test_traverse_ast_uart_native(self):
def update_rules_fn(
rules: list[str],
target_name: str,
srcs_content: str,
unconditional_deps: list[str],
deps_selects: list[str],
is_root: bool,
) -> list[str]:
rules.append(f"srcs_content: {srcs_content}")
return rules
ast = [{'type': 'unconditional_source', 'srcs': ['uart_native_pty.c']}]
rules = common.traverse_ast(ast, 'uart_native_pty', update_rules_fn)
self.assertEqual(len(rules), 1)
self.assertIn('defines = ["_POSIX_C_SOURCE=200809L"]', rules[0])
if __name__ == '__main__':
unittest.main()