1# Copyright 2022 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Tests for pw_build.project_builder_prefs""" 15 16import argparse 17import copy 18from pathlib import Path 19import tempfile 20from typing import Any 21import unittest 22from unittest.mock import MagicMock 23 24from pw_build.project_builder_argparse import add_project_builder_arguments 25from pw_build.project_builder_prefs import ( 26 ProjectBuilderPrefs, 27 _DEFAULT_CONFIG, 28 load_defaults_from_argparse, 29) 30 31from pw_config_loader import yaml_config_loader_mixin 32 33 34def _create_tempfile(content: str) -> Path: 35 with tempfile.NamedTemporaryFile( 36 prefix=f'{__package__}', delete=False 37 ) as output_file: 38 output_file.write(content.encode('UTF-8')) 39 return Path(output_file.name) 40 41 42class TestProjectBuilderPrefs(unittest.TestCase): 43 """Tests for ProjectBuilderPrefs.""" 44 45 maxDiff = None 46 47 def test_load_no_existing_files(self) -> None: 48 # Create a prefs instance with no loaded config. 49 prefs = ProjectBuilderPrefs( 50 load_argparse_arguments=add_project_builder_arguments, 51 project_file=False, 52 project_user_file=False, 53 user_file=False, 54 ) 55 # Construct an expected result config. 56 expected_config: dict[Any, Any] = {} 57 expected_config.update(_DEFAULT_CONFIG) 58 expected_config.update( 59 load_defaults_from_argparse(add_project_builder_arguments) 60 ) 61 62 self.assertEqual( 63 prefs._config, expected_config # pylint: disable=protected-access 64 ) 65 66 def test_apply_command_line_args(self) -> None: 67 """Check command line args are applied to watch preferences.""" 68 # Load default command line arg values. 69 defaults_from_argparse = load_defaults_from_argparse( 70 add_project_builder_arguments 71 ) 72 73 # Create a prefs instance with the test config file. 74 prefs = ProjectBuilderPrefs( 75 load_argparse_arguments=add_project_builder_arguments, 76 project_file=False, 77 project_user_file=False, 78 user_file=False, 79 ) 80 81 # Construct an expected result config. 82 expected_config: dict[Any, Any] = copy.copy(_DEFAULT_CONFIG) 83 expected_config.update(defaults_from_argparse) 84 85 # pylint: disable=protected-access 86 prefs._update_config = MagicMock( # type: ignore 87 wraps=prefs._update_config 88 ) 89 # pylint: enable=protected-access 90 91 args_dict = copy.deepcopy(defaults_from_argparse) 92 changed_args = { 93 'jobs': 8, 94 'colors': False, 95 'build_system_commands': [ 96 ['out', 'bazel build'], 97 ['out', 'bazel test'], 98 ], 99 } 100 args_dict.update(changed_args) 101 102 prefs.apply_command_line_args(argparse.Namespace(**args_dict)) 103 104 # apply_command_line_args modifies build_system_commands to match the 105 # prefs dict format. 106 changed_args['build_system_commands'] = { 107 'default': {'commands': [{'command': 'ninja', 'extra_args': []}]}, 108 'out': { 109 'commands': [ 110 {'command': 'bazel', 'extra_args': ['build']}, 111 {'command': 'bazel', 'extra_args': ['test']}, 112 ], 113 }, 114 } 115 116 # Check that only args changed from their defaults are applied. 117 # pylint: disable=protected-access 118 prefs._update_config.assert_called_once_with( 119 changed_args, 120 yaml_config_loader_mixin.Stage.DEFAULT, 121 ) 122 # pylint: enable=protected-access 123 124 # Check the result includes the project_config settings and the 125 # changed_args. 126 expected_config.update(changed_args) 127 # pylint: disable=protected-access 128 self.assertEqual(prefs._config, expected_config) 129 # pylint: enable=protected-access 130 131 132if __name__ == '__main__': 133 unittest.main() 134