blob: 2e4e9527dd4aeab3d781fcde61fe70766149e01a [file] [edit]
# Copyright (c) 2026 Project CHIP 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
#
# http://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.
import importlib.util
import json
import os
import tempfile
import unittest
# configure.impl uses a non-package filename; import it by path
_spec = importlib.util.spec_from_file_location("configure_impl", os.path.join(os.path.dirname(__file__), "configure.impl.py"))
impl = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(impl)
# A small fixture modeled on real `gn args --list --json` output.
# Includes: bool (default true/false), string, integer, list, and a
# collision where stripping prefixes from two args yields the same alias.
FIXTURE = [
{"name": "chip_enable_wifi", "comment": "Enable wifi.", "default": {
"file": "//third_party/connectedhomeip/src/platform/device.gni", "line": 69, "value": "false"}},
{"name": "chip_automation_logging", "default": {
"file": "//third_party/connectedhomeip/src/lib/support/logging.gni", "line": 10, "value": "true"}},
{"name": "chip_crypto", "comment": "Crypto implementation.", "default": {
"file": "//third_party/connectedhomeip/src/crypto/crypto.gni", "line": 17, "value": "\"\""}},
{"name": "chip_log_message_max_size", "default": {
"file": "//third_party/connectedhomeip/src/lib/support/logging.gni", "line": 5, "value": "-1"}},
{"name": "chip_project_config_include_dirs", "comment": "Extra include dirs.", "default": {
"file": "//third_party/connectedhomeip/src/system/BUILD.gn", "line": 39, "value": "[]"}},
# Collision: both reduce to alias "debug" when chip_ prefix is stripped
{"name": "chip_use_debug", "default": {"file": "//third_party/connectedhomeip/BUILD.gn", "line": 1, "value": "false"}},
{"name": "chip_config_debug", "default": {"file": "//third_party/connectedhomeip/BUILD.gn", "line": 2, "value": "false"}},
# A project-level arg (not under //third_party/connectedhomeip/)
{"name": "project_foo", "default": {"file": "//src/args.gni", "line": 1, "value": "\"bar\""}},
# GN built-ins needed for triplet tests (no source file)
{"name": "target_cpu", "default": {"value": "\"\""}},
{"name": "target_os", "default": {"value": "\"\""}},
{"name": "host_cpu", "default": {"value": "\"\""}},
{"name": "host_os", "default": {"value": "\"\""}},
]
def make_processor(fixture=FIXTURE):
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
json.dump(fixture, f)
f.flush()
try:
return impl.ProjectArgProcessor(f.name)
finally:
os.unlink(f.name)
class TestProjectArgProcessor(unittest.TestCase):
def test_arg_types(self):
p = make_processor()
self.assertEqual(p.gn_args['chip_enable_wifi'].type, 'b')
self.assertEqual(p.gn_args['chip_automation_logging'].type, 'b')
self.assertEqual(p.gn_args['chip_crypto'].type, 's')
self.assertEqual(p.gn_args['chip_log_message_max_size'].type, 'i')
self.assertEqual(p.gn_args['chip_project_config_include_dirs'].type, '[')
def test_aliases(self):
p = make_processor()
# chip_enable_wifi -> shortest unique alias is "wifi"
self.assertEqual(p.gn_args['chip_enable_wifi'].alias, 'wifi')
self.assertIs(p.options['wifi'], p.gn_args['chip_enable_wifi'])
# longer aliases work too
self.assertIs(p.options['enable-wifi'], p.gn_args['chip_enable_wifi'])
self.assertIs(p.options['chip-enable-wifi'], p.gn_args['chip_enable_wifi'])
# chip_crypto -> "crypto"
self.assertEqual(p.gn_args['chip_crypto'].alias, 'crypto')
# chip_log_message_max_size -> "log-message-max-size"
self.assertEqual(p.gn_args['chip_log_message_max_size'].alias, 'log-message-max-size')
def test_collision_excludes_ambiguous_alias(self):
p = make_processor()
# Both chip_use_debug and chip_config_debug would map to "debug"
self.assertNotIn('debug', p.options)
# But they get longer unique aliases
self.assertEqual(p.gn_args['chip_use_debug'].alias, 'use-debug')
self.assertEqual(p.gn_args['chip_config_debug'].alias, 'config-debug')
def test_process_enable_parameter(self):
p = make_processor()
p.process_parameters(['--enable-wifi'])
self.assertEqual(p.args['chip_enable_wifi'], 'true')
def test_process_enable_parameter_disable(self):
p = make_processor()
p.process_parameters(['--enable-wifi=no'])
self.assertEqual(p.args['chip_enable_wifi'], 'false')
def test_process_enable_rejects_non_bool(self):
p = make_processor()
with self.assertRaises(SystemExit):
p.process_parameters(['--enable-crypto'])
def test_process_string_parameter(self):
p = make_processor()
p.process_parameters(['--crypto=openssl'])
self.assertEqual(p.args['chip_crypto'], '"openssl"')
def test_process_integer_parameter(self):
p = make_processor()
p.process_parameters(['--log-message-max-size=256'])
self.assertEqual(p.args['chip_log_message_max_size'], '256')
def test_process_triplet(self):
p = make_processor()
p.process_parameters(['--target=aarch64-linux'])
self.assertEqual(p.args['target_cpu'], '"aarch64"')
self.assertEqual(p.args['target_os'], '"linux"')
def test_process_triplet_with_vendor(self):
p = make_processor()
p.process_parameters(['--build=arm-unknown-linux-gnueabihf'])
self.assertEqual(p.args['host_cpu'], '"arm"')
self.assertEqual(p.args['host_os'], '"linux"')
def test_bool_arg_rejects_generic_parameter(self):
p = make_processor()
self.assertEqual(p.options['wifi'].type, 'b')
with self.assertRaises(SystemExit):
p.process_parameters(['--wifi=yes'])
def test_unknown_option_warns(self):
p = make_processor()
# Unknown options produce a warning but don't fail
p.process_parameters(['--enable-nonexistent'])
self.assertEqual(len(p.args), 0)
def test_invalid_argument_format(self):
p = make_processor()
with self.assertRaises(SystemExit):
p.process_parameters(['not-an-option'])
def test_multiple_parameters(self):
p = make_processor()
p.process_parameters(['--enable-wifi', '--crypto=boringssl', '--log-message-max-size=512'])
self.assertEqual(p.args['chip_enable_wifi'], 'true')
self.assertEqual(p.args['chip_crypto'], '"boringssl"')
self.assertEqual(p.args['chip_log_message_max_size'], '512')
if __name__ == '__main__':
unittest.main()