| # Copyright 2026 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. |
| |
| import unittest |
| import os |
| import tempfile |
| import shutil |
| import sys |
| import json |
| |
| # Import the script to test |
| sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) |
| import parse_sysbuild_metadata |
| |
| class TestParseSysbuildMetadata(unittest.TestCase): |
| def setUp(self): |
| self.test_dir = tempfile.mkdtemp() |
| |
| def tearDown(self): |
| shutil.rmtree(self.test_dir) |
| |
| def test_parse_empty_app(self): |
| apps = {"//apps/empty": self.test_dir} |
| orig_argv = sys.argv |
| sys.argv = [sys.argv[0], "--apps-json", json.dumps(apps)] |
| |
| try: |
| import io |
| from contextlib import redirect_stdout |
| |
| f = io.StringIO() |
| with redirect_stdout(f): |
| parse_sysbuild_metadata.main() |
| |
| output = json.loads(f.getvalue()) |
| self.assertEqual(output["custom_repos"], []) |
| finally: |
| sys.argv = orig_argv |
| |
| def test_parse_global_helpers(self): |
| app_path = os.path.join(self.test_dir, "my_app") |
| os.makedirs(app_path) |
| |
| with open(os.path.join(app_path, "sysbuild.yml"), 'w') as f: |
| f.write(""" |
| helpers: |
| mcuboot: |
| target: "@mcuboot//boot/zephyr:zephyr_project" |
| """) |
| |
| apps = {"//apps/my_app": app_path} |
| |
| orig_argv = sys.argv |
| sys.argv = [sys.argv[0], "--apps-json", json.dumps(apps)] |
| |
| try: |
| import io |
| from contextlib import redirect_stdout |
| |
| f = io.StringIO() |
| with redirect_stdout(f): |
| parse_sysbuild_metadata.main() |
| |
| output = json.loads(f.getvalue()) |
| self.assertIn("//apps/my_app", output["raw_metadata"]) |
| self.assertIn("mcuboot", output["raw_metadata"]["//apps/my_app"]["helpers"]) |
| finally: |
| sys.argv = orig_argv |
| |
| def test_parse_custom_repo_detection_from_conf(self): |
| app_path = os.path.join(self.test_dir, "my_app") |
| os.makedirs(app_path) |
| |
| with open(os.path.join(app_path, "sysbuild.yml"), 'w') as f: |
| f.write(""" |
| helpers: |
| helper_app: |
| target: "//hello_bazel" |
| """) |
| |
| # Create sysbuild.conf with helper setting to trigger custom repo |
| with open(os.path.join(app_path, "sysbuild.conf"), 'w') as f: |
| f.write("helper_app_CONFIG_LOG=y\n") |
| |
| apps = {"//apps/my_app": app_path} |
| |
| orig_argv = sys.argv |
| sys.argv = [sys.argv[0], "--apps-json", json.dumps(apps)] |
| |
| try: |
| import io |
| from contextlib import redirect_stdout |
| |
| f = io.StringIO() |
| with redirect_stdout(f): |
| parse_sysbuild_metadata.main() |
| |
| output = json.loads(f.getvalue()) |
| self.assertEqual(len(output["custom_repos"]), 1) |
| self.assertEqual(output["custom_repos"][0]["helper_name"], "helper_app") |
| self.assertIn("CONFIG_LOG=y", output["custom_repos"][0]["extra_kconfig"]) |
| finally: |
| sys.argv = orig_argv |
| |
| def test_parse_namespaced_settings(self): |
| app_path = os.path.join(self.test_dir, "my_app") |
| os.makedirs(app_path) |
| |
| conf_file = os.path.join(app_path, "sysbuild.conf") |
| with open(conf_file, 'w') as f: |
| f.write(""" |
| mcuboot_CONFIG_BOOT_SIGNATURE_TYPE_RSA=y |
| net_app_CONFIG_SOME_OPTION=value |
| """) |
| |
| apps = {"//apps/my_app": app_path} |
| |
| orig_argv = sys.argv |
| sys.argv = [sys.argv[0], "--apps-json", json.dumps(apps)] |
| |
| try: |
| import io |
| from contextlib import redirect_stdout |
| |
| f = io.StringIO() |
| with redirect_stdout(f): |
| parse_sysbuild_metadata.main() |
| |
| output = json.loads(f.getvalue()) |
| self.assertIn("translated_confs", output) |
| translated = output["translated_confs"] |
| self.assertIn("//apps/my_app", translated) |
| self.assertIn("mcuboot", translated["//apps/my_app"]) |
| self.assertIn("CONFIG_BOOT_SIGNATURE_TYPE_RSA=y", translated["//apps/my_app"]["mcuboot"]) |
| self.assertIn("net_app", translated["//apps/my_app"]) |
| self.assertIn("CONFIG_SOME_OPTION=value", translated["//apps/my_app"]["net_app"]) |
| finally: |
| sys.argv = orig_argv |
| |
| def test_translate_sb_config(self): |
| app_path = os.path.join(self.test_dir, "my_app") |
| os.makedirs(app_path) |
| |
| conf_file = os.path.join(app_path, "sysbuild.conf") |
| with open(conf_file, 'w') as f: |
| f.write(""" |
| SB_CONFIG_BOOTLOADER_MCUBOOT=y |
| SB_CONFIG_MCUBOOT_MODE_UPGRADE_ONLY=y |
| """) |
| |
| apps = {"//apps/my_app": app_path} |
| |
| orig_argv = sys.argv |
| sys.argv = [sys.argv[0], "--apps-json", json.dumps(apps)] |
| |
| try: |
| import io |
| from contextlib import redirect_stdout |
| |
| f = io.StringIO() |
| with redirect_stdout(f): |
| parse_sysbuild_metadata.main() |
| |
| output = json.loads(f.getvalue()) |
| self.assertIn("translated_confs", output) |
| translated = output["translated_confs"] |
| self.assertIn("//apps/my_app", translated) |
| self.assertIn("mcuboot", translated["//apps/my_app"]) |
| self.assertIn("CONFIG_MCUBOOT_BOOTLOADER_MODE_UPGRADE_ONLY=y", translated["//apps/my_app"]["mcuboot"]) |
| self.assertIn("CONFIG_BOOTLOADER_MCUBOOT=y", translated["//apps/my_app"]["mcuboot"]) |
| self.assertIn("main", translated["//apps/my_app"]) |
| self.assertIn("CONFIG_BOOTLOADER_MCUBOOT=y", translated["//apps/my_app"]["main"]) |
| finally: |
| sys.argv = orig_argv |
| |
| if __name__ == '__main__': |
| unittest.main() |