|
6 | 6 | import os |
7 | 7 | import pathlib |
8 | 8 | import subprocess |
| 9 | +import textwrap |
9 | 10 | from typing import Any |
10 | 11 |
|
11 | 12 | import pytest |
@@ -93,6 +94,62 @@ def test_config_global(): |
93 | 94 | assert 'pytest' not in lcl |
94 | 95 |
|
95 | 96 |
|
| 97 | +TEST_CASES_CONFIG_LIST_PATHS = [ |
| 98 | + # (flag, env_var) |
| 99 | + ('--local', 'WEST_CONFIG_LOCAL'), |
| 100 | + ('--system', 'WEST_CONFIG_SYSTEM'), |
| 101 | + ('--global', 'WEST_CONFIG_GLOBAL'), |
| 102 | +] |
| 103 | + |
| 104 | + |
| 105 | +@pytest.mark.parametrize("test_case", TEST_CASES_CONFIG_LIST_PATHS) |
| 106 | +def test_config_list_paths(test_case): |
| 107 | + flag, env_var = test_case |
| 108 | + |
| 109 | + # create the config |
| 110 | + cmd(f'config {flag} pytest.key val') |
| 111 | + |
| 112 | + # check that the config is listed now |
| 113 | + stdout = cmd(f'config {flag} --list-paths') |
| 114 | + config_path = pathlib.Path(os.environ[env_var]) |
| 115 | + assert f'{config_path}' == stdout.rstrip() |
| 116 | + |
| 117 | + # no config is listed (since it does not exist) |
| 118 | + config_path.unlink() |
| 119 | + stdout = cmd(f'config {flag} --list-paths') |
| 120 | + assert '' == stdout.rstrip() |
| 121 | + |
| 122 | + |
| 123 | +def test_config_list_paths_extended(): |
| 124 | + WEST_CONFIG_LOCAL = os.environ['WEST_CONFIG_LOCAL'] |
| 125 | + WEST_CONFIG_GLOBAL = os.environ['WEST_CONFIG_GLOBAL'] |
| 126 | + WEST_CONFIG_SYSTEM = os.environ['WEST_CONFIG_SYSTEM'] |
| 127 | + |
| 128 | + # create the configs |
| 129 | + cmd('config --local pytest.key val') |
| 130 | + cmd('config --global pytest.key val') |
| 131 | + cmd('config --system pytest.key val') |
| 132 | + |
| 133 | + # list the configs |
| 134 | + stdout = cmd('config --list-paths') |
| 135 | + assert ( |
| 136 | + stdout.splitlines() |
| 137 | + == textwrap.dedent(f'''\ |
| 138 | + {WEST_CONFIG_GLOBAL} |
| 139 | + {WEST_CONFIG_SYSTEM} |
| 140 | + {WEST_CONFIG_LOCAL} |
| 141 | + ''').splitlines() |
| 142 | + ) |
| 143 | + |
| 144 | + # do not list any configs if no config files exist |
| 145 | + # (Note: even no local config exists, same as outside any west workspace) |
| 146 | + pathlib.Path(WEST_CONFIG_GLOBAL).unlink() |
| 147 | + pathlib.Path(WEST_CONFIG_SYSTEM).unlink() |
| 148 | + pathlib.Path(WEST_CONFIG_LOCAL).unlink() |
| 149 | + stdout = cmd('config --list-paths') |
| 150 | + assert stdout.splitlines() == [] |
| 151 | + |
| 152 | + |
96 | 153 | def test_config_local(): |
97 | 154 | # test_config_system for local variables. |
98 | 155 | cmd('config --local pytest.local foo') |
@@ -519,6 +576,81 @@ def test_config_precedence(): |
519 | 576 | assert cfg(f=LOCAL)['pytest']['precedence'] == 'local' |
520 | 577 |
|
521 | 578 |
|
| 579 | +def test_config_multiple(config_tmpdir): |
| 580 | + # Verify that local settings take precedence over global ones, |
| 581 | + # but that both values are still available, and that setting |
| 582 | + # either doesn't affect system settings. |
| 583 | + def write_config(config_file, section, key1, value1, key2, value2): |
| 584 | + config_file.parent.mkdir(exist_ok=True) |
| 585 | + |
| 586 | + content = textwrap.dedent(f''' |
| 587 | + [{section}] |
| 588 | + {key1} = {value1} |
| 589 | + {key2} = {value2} |
| 590 | + ''') |
| 591 | + |
| 592 | + with open(config_file, 'w') as conf: |
| 593 | + conf.write(content) |
| 594 | + |
| 595 | + # config file paths |
| 596 | + config_dir = pathlib.Path(config_tmpdir) / 'configs' |
| 597 | + config_s1 = config_dir / 'system1' |
| 598 | + config_s2 = config_dir / 'system2' |
| 599 | + config_g1 = config_dir / 'global1' |
| 600 | + config_g2 = config_dir / 'global2' |
| 601 | + config_l1 = config_dir / 'local1' |
| 602 | + config_l2 = config_dir / 'local2' |
| 603 | + |
| 604 | + # create some configs with |
| 605 | + # - some individual option per config file |
| 606 | + # - the same option defined in multiple configs |
| 607 | + write_config(config_s1, 'sec', 's', 1, 's1', 1) |
| 608 | + write_config(config_s2, 'sec', 's', 2, 's2', 2) |
| 609 | + write_config(config_g1, 'sec', 'g', 1, 'g1', 1) |
| 610 | + write_config(config_g2, 'sec', 'g', 2, 'g2', 2) |
| 611 | + write_config(config_l1, 'sec', 'l', 1, 'l1', 1) |
| 612 | + write_config(config_l2, 'sec', 'l', 2, 'l2', 2) |
| 613 | + |
| 614 | + # specify multiple configs for each config level (separated by os.pathsep) |
| 615 | + os.environ["WEST_CONFIG_GLOBAL"] = f'{config_g1}{os.pathsep}{config_g2}' |
| 616 | + os.environ["WEST_CONFIG_SYSTEM"] = f'{config_s1}{os.pathsep}{config_s2}' |
| 617 | + os.environ["WEST_CONFIG_LOCAL"] = f'{config_l1}{os.pathsep}{config_l2}' |
| 618 | + |
| 619 | + # check that all individual options are applied |
| 620 | + stdout = cmd('config --system sec.s1').rstrip() |
| 621 | + assert stdout == '1' |
| 622 | + stdout = cmd('config --system sec.s2').rstrip() |
| 623 | + assert stdout == '2' |
| 624 | + stdout = cmd('config --global sec.g1').rstrip() |
| 625 | + assert stdout == '1' |
| 626 | + stdout = cmd('config --global sec.g2').rstrip() |
| 627 | + assert stdout == '2' |
| 628 | + stdout = cmd('config --local sec.l1').rstrip() |
| 629 | + assert stdout == '1' |
| 630 | + stdout = cmd('config --local sec.l2').rstrip() |
| 631 | + assert stdout == '2' |
| 632 | + |
| 633 | + # check that options from latest config overrides |
| 634 | + stdout = cmd('config --system sec.s').rstrip() |
| 635 | + assert stdout == '2' |
| 636 | + stdout = cmd('config --global sec.g').rstrip() |
| 637 | + assert stdout == '2' |
| 638 | + stdout = cmd('config --local sec.l').rstrip() |
| 639 | + assert stdout == '2' |
| 640 | + |
| 641 | + # check that list-paths gives correct output |
| 642 | + stdout = cmd('config --global --list-paths') |
| 643 | + assert [str(config_g1), str(config_g2)] == stdout.rstrip().splitlines() |
| 644 | + stdout = cmd('config --system --list-paths') |
| 645 | + assert [str(config_s1), str(config_s2)] == stdout.rstrip().splitlines() |
| 646 | + stdout = cmd('config --local --list-paths') |
| 647 | + assert [str(config_l1), str(config_l2)] == stdout.rstrip().splitlines() |
| 648 | + |
| 649 | + # writing not possible if multiple configs are used |
| 650 | + err_msg = cmd_raises('config --local sec.l3 3', subprocess.CalledProcessError) |
| 651 | + assert 'Cannot write if multiple configs in use' in err_msg |
| 652 | + |
| 653 | + |
522 | 654 | def test_config_missing_key(): |
523 | 655 | err_msg = cmd_raises('config pytest', subprocess.CalledProcessError) |
524 | 656 | assert 'invalid configuration option "pytest"; expected "section.key" format' in err_msg |
|
0 commit comments