a128400376d1f51845e8e75b32281a870fb354a7
Marco Ricci Add prototype command-line...

Marco Ricci authored 2 months ago

1) # SPDX-FileCopyrightText: 2024 Marco Ricci <m@the13thletter.info>
2) #
3) # SPDX-License-Identifier: MIT
4) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

5) from __future__ import annotations
6) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

7) import contextlib
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

8) import json
9) import os
Marco Ricci Create the configuration di...

Marco Ricci authored 1 month ago

10) import shutil
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

11) import socket
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

12) from typing import TYPE_CHECKING
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

13) 
Marco Ricci Add prototype command-line...

Marco Ricci authored 2 months ago

14) import click.testing
15) import pytest
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

16) from typing_extensions import NamedTuple
17) 
18) import derivepassphrase as dpp
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

19) import tests
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 1 month ago

20) from derivepassphrase import _types, cli, ssh_agent
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

21) 
22) if TYPE_CHECKING:
23)     from collections.abc import Callable
24) 
25)     from typing_extensions import Any
Marco Ricci Add prototype command-line...

Marco Ricci authored 2 months ago

26) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

27) DUMMY_SERVICE = tests.DUMMY_SERVICE
28) DUMMY_PASSPHRASE = tests.DUMMY_PASSPHRASE
29) DUMMY_CONFIG_SETTINGS = tests.DUMMY_CONFIG_SETTINGS
30) DUMMY_RESULT_PASSPHRASE = tests.DUMMY_RESULT_PASSPHRASE
31) DUMMY_RESULT_KEY1 = tests.DUMMY_RESULT_KEY1
32) DUMMY_PHRASE_FROM_KEY1_RAW = tests.DUMMY_PHRASE_FROM_KEY1_RAW
33) DUMMY_PHRASE_FROM_KEY1 = tests.DUMMY_PHRASE_FROM_KEY1
34) 
35) DUMMY_KEY1 = tests.DUMMY_KEY1
36) DUMMY_KEY1_B64 = tests.DUMMY_KEY1_B64
37) DUMMY_KEY2 = tests.DUMMY_KEY2
Marco Ricci Avoid crashing when overrid...

Marco Ricci authored 1 month ago

38) DUMMY_KEY2_B64 = tests.DUMMY_KEY2_B64
39) DUMMY_KEY3 = tests.DUMMY_KEY3
40) DUMMY_KEY3_B64 = tests.DUMMY_KEY3_B64
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

41) 
42) 
43) class IncompatibleConfiguration(NamedTuple):
44)     other_options: list[tuple[str, ...]]
45)     needs_service: bool | None
46)     input: bytes | None
47) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

48) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

49) class SingleConfiguration(NamedTuple):
50)     needs_service: bool | None
51)     input: bytes | None
52)     check_success: bool
53) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

54) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

55) class OptionCombination(NamedTuple):
56)     options: list[str]
57)     incompatible: bool
58)     needs_service: bool | None
59)     input: bytes | None
60)     check_success: bool
61) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

62) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

63) PASSWORD_GENERATION_OPTIONS: list[tuple[str, ...]] = [
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

64)     ('--phrase',),
65)     ('--key',),
66)     ('--length', '20'),
67)     ('--repeat', '20'),
68)     ('--lower', '1'),
69)     ('--upper', '1'),
70)     ('--number', '1'),
71)     ('--space', '1'),
72)     ('--dash', '1'),
73)     ('--symbol', '1'),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

74) ]
75) CONFIGURATION_OPTIONS: list[tuple[str, ...]] = [
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

76)     ('--notes',),
77)     ('--config',),
78)     ('--delete',),
79)     ('--delete-globals',),
80)     ('--clear',),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

81) ]
82) CONFIGURATION_COMMANDS: list[tuple[str, ...]] = [
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

83)     ('--notes',),
84)     ('--delete',),
85)     ('--delete-globals',),
86)     ('--clear',),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

87) ]
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

88) STORAGE_OPTIONS: list[tuple[str, ...]] = [('--export', '-'), ('--import', '-')]
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

89) INCOMPATIBLE: dict[tuple[str, ...], IncompatibleConfiguration] = {
90)     ('--phrase',): IncompatibleConfiguration(
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

91)         [('--key',), *CONFIGURATION_COMMANDS, *STORAGE_OPTIONS],
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

92)         True,
93)         DUMMY_PASSPHRASE,
94)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

95)     ('--key',): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

96)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
97)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

98)     ('--length', '20'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

99)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
100)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

101)     ('--repeat', '20'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

102)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
103)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

104)     ('--lower', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

105)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
106)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

107)     ('--upper', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

108)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
109)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

110)     ('--number', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

111)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
112)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

113)     ('--space', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

114)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
115)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

116)     ('--dash', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

117)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
118)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

119)     ('--symbol', '1'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

120)         CONFIGURATION_COMMANDS + STORAGE_OPTIONS, True, DUMMY_PASSPHRASE
121)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

122)     ('--notes',): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

123)         [
124)             ('--config',),
125)             ('--delete',),
126)             ('--delete-globals',),
127)             ('--clear',),
128)             *STORAGE_OPTIONS,
129)         ],
130)         True,
131)         None,
132)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

133)     ('--config', '-p'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

134)         [('--delete',), ('--delete-globals',), ('--clear',), *STORAGE_OPTIONS],
135)         None,
136)         DUMMY_PASSPHRASE,
137)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

138)     ('--delete',): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

139)         [('--delete-globals',), ('--clear',), *STORAGE_OPTIONS], True, None
140)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

141)     ('--delete-globals',): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

142)         [('--clear',), *STORAGE_OPTIONS], False, None
143)     ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

144)     ('--clear',): IncompatibleConfiguration(STORAGE_OPTIONS, False, None),
145)     ('--export', '-'): IncompatibleConfiguration(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

146)         [('--import', '-')], False, None
147)     ),
148)     ('--import', '-'): IncompatibleConfiguration([], False, None),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

149) }
150) SINGLES: dict[tuple[str, ...], SingleConfiguration] = {
151)     ('--phrase',): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
152)     ('--key',): SingleConfiguration(True, None, False),
153)     ('--length', '20'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
154)     ('--repeat', '20'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
155)     ('--lower', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
156)     ('--upper', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
157)     ('--number', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
158)     ('--space', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
159)     ('--dash', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
160)     ('--symbol', '1'): SingleConfiguration(True, DUMMY_PASSPHRASE, True),
161)     ('--notes',): SingleConfiguration(True, None, False),
162)     ('--config', '-p'): SingleConfiguration(None, DUMMY_PASSPHRASE, False),
163)     ('--delete',): SingleConfiguration(True, None, False),
164)     ('--delete-globals',): SingleConfiguration(False, None, True),
165)     ('--clear',): SingleConfiguration(False, None, True),
166)     ('--export', '-'): SingleConfiguration(False, None, True),
167)     ('--import', '-'): SingleConfiguration(False, b'{"services": {}}', True),
168) }
169) INTERESTING_OPTION_COMBINATIONS: list[OptionCombination] = []
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

170) config: IncompatibleConfiguration | SingleConfiguration
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

171) for opt, config in INCOMPATIBLE.items():
172)     for opt2 in config.other_options:
173)         INTERESTING_OPTION_COMBINATIONS.extend([
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

174)             OptionCombination(
175)                 options=list(opt + opt2),
176)                 incompatible=True,
177)                 needs_service=config.needs_service,
178)                 input=config.input,
179)                 check_success=False,
180)             ),
181)             OptionCombination(
182)                 options=list(opt2 + opt),
183)                 incompatible=True,
184)                 needs_service=config.needs_service,
185)                 input=config.input,
186)                 check_success=False,
187)             ),
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

188)         ])
189) for opt, config in SINGLES.items():
190)     INTERESTING_OPTION_COMBINATIONS.append(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

191)         OptionCombination(
192)             options=list(opt),
193)             incompatible=False,
194)             needs_service=config.needs_service,
195)             input=config.input,
196)             check_success=config.check_success,
197)         )
198)     )
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

199) 
200) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

201) class TestCLI:
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

202)     def test_200_help_output(self, monkeypatch: Any) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

203)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

204)         with tests.isolated_config(
205)             monkeypatch=monkeypatch,
206)             runner=runner,
207)             config={'services': {}},
208)         ):
209)             result = runner.invoke(
210)                 cli.derivepassphrase, ['--help'], catch_exceptions=False
211)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

212)         assert result.exit_code == 0
213)         assert (
214)             'Password generation:\n' in result.output
215)         ), 'Option groups not respected in help text.'
216)         assert (
217)             'Use NUMBER=0, e.g. "--symbol 0"' in result.output
218)         ), 'Option group epilog not printed.'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

219) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

220)     @pytest.mark.parametrize(
221)         'charset_name', ['lower', 'upper', 'number', 'space', 'dash', 'symbol']
222)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

223)     def test_201_disable_character_set(
224)         self, monkeypatch: Any, charset_name: str
225)     ) -> None:
226)         monkeypatch.setattr(cli, '_prompt_for_passphrase', tests.auto_prompt)
227)         option = f'--{charset_name}'
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

228)         charset = dpp.vault.Vault._CHARSETS[charset_name].decode('ascii')
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

229)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

230)         with tests.isolated_config(
231)             monkeypatch=monkeypatch,
232)             runner=runner,
233)             config={'services': {}},
234)         ):
235)             result = runner.invoke(
236)                 cli.derivepassphrase,
237)                 [option, '0', '-p', DUMMY_SERVICE],
238)                 input=DUMMY_PASSPHRASE,
239)                 catch_exceptions=False,
240)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

241)         assert (
242)             result.exit_code == 0
243)         ), f'program died unexpectedly with exit code {result.exit_code}'
244)         assert (
245)             not result.stderr_bytes
246)         ), f'program barfed on stderr: {result.stderr_bytes!r}'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

247)         for c in charset:
248)             assert c not in result.stdout, (
249)                 f'derived password contains forbidden character {c!r}: '
250)                 f'{result.stdout!r}'
251)             )
Marco Ricci Add prototype command-line...

Marco Ricci authored 2 months ago

252) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

253)     def test_202_disable_repetition(self, monkeypatch: Any) -> None:
254)         monkeypatch.setattr(cli, '_prompt_for_passphrase', tests.auto_prompt)
255)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

256)         with tests.isolated_config(
257)             monkeypatch=monkeypatch,
258)             runner=runner,
259)             config={'services': {}},
260)         ):
261)             result = runner.invoke(
262)                 cli.derivepassphrase,
263)                 ['--repeat', '0', '-p', DUMMY_SERVICE],
264)                 input=DUMMY_PASSPHRASE,
265)                 catch_exceptions=False,
266)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

267)         assert (
268)             result.exit_code == 0
269)         ), f'program died unexpectedly with exit code {result.exit_code}'
270)         assert (
271)             not result.stderr_bytes
272)         ), f'program barfed on stderr: {result.stderr_bytes!r}'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

273)         passphrase = result.stdout.rstrip('\r\n')
274)         for i in range(len(passphrase) - 1):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

275)             assert passphrase[i : i + 1] != passphrase[i + 1 : i + 2], (
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

276)                 f'derived password contains repeated character '
277)                 f'at position {i}: {result.stdout!r}'
278)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

279) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

280)     @pytest.mark.parametrize(
281)         'config',
282)         [
283)             pytest.param(
284)                 {
285)                     'global': {'key': DUMMY_KEY1_B64},
286)                     'services': {DUMMY_SERVICE: DUMMY_CONFIG_SETTINGS},
287)                 },
288)                 id='global',
289)             ),
290)             pytest.param(
291)                 {
292)                     'global': {
293)                         'phrase': DUMMY_PASSPHRASE.rstrip(b'\n').decode(
294)                             'ASCII'
295)                         )
296)                     },
297)                     'services': {
298)                         DUMMY_SERVICE: {
299)                             'key': DUMMY_KEY1_B64,
300)                             **DUMMY_CONFIG_SETTINGS,
301)                         }
302)                     },
303)                 },
304)                 id='service',
305)             ),
306)         ],
307)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

308)     def test_204a_key_from_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

309)         self,
310)         monkeypatch: Any,
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 1 month ago

311)         config: _types.VaultConfig,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

312)     ) -> None:
313)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

314)         with tests.isolated_config(
315)             monkeypatch=monkeypatch, runner=runner, config=config
316)         ):
317)             monkeypatch.setattr(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

318)                 dpp.vault.Vault, 'phrase_from_key', tests.phrase_from_key
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

319)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

320)             result = runner.invoke(
321)                 cli.derivepassphrase, [DUMMY_SERVICE], catch_exceptions=False
322)             )
323)             assert (result.exit_code, result.stderr_bytes) == (
324)                 0,
325)                 b'',
326)             ), 'program exited with failure'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

327)             assert (
328)                 result.stdout_bytes.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

329)             ), 'program generated unexpected result (phrase instead of key)'
330)             assert (
331)                 result.stdout_bytes.rstrip(b'\n') == DUMMY_RESULT_KEY1
332)             ), 'program generated unexpected result (wrong settings?)'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

333) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

334)     def test_204b_key_from_command_line(self, monkeypatch: Any) -> None:
335)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

336)         with tests.isolated_config(
337)             monkeypatch=monkeypatch,
338)             runner=runner,
339)             config={'services': {DUMMY_SERVICE: DUMMY_CONFIG_SETTINGS}},
340)         ):
341)             monkeypatch.setattr(
342)                 cli, '_get_suitable_ssh_keys', tests.suitable_ssh_keys
343)             )
344)             monkeypatch.setattr(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

345)                 dpp.vault.Vault, 'phrase_from_key', tests.phrase_from_key
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

346)             )
347)             result = runner.invoke(
348)                 cli.derivepassphrase,
349)                 ['-k', DUMMY_SERVICE],
350)                 input=b'1\n',
351)                 catch_exceptions=False,
352)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

353)             assert result.exit_code == 0, 'program exited with failure'
354)             assert result.stdout_bytes, 'program output expected'
355)             last_line = result.stdout_bytes.splitlines(True)[-1]
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

356)             assert (
357)                 last_line.rstrip(b'\n') != DUMMY_RESULT_PASSPHRASE
358)             ), 'program generated unexpected result (phrase instead of key)'
359)             assert (
360)                 last_line.rstrip(b'\n') == DUMMY_RESULT_KEY1
361)             ), 'program generated unexpected result (wrong settings?)'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

362) 
Marco Ricci Avoid crashing when overrid...

Marco Ricci authored 1 month ago

363)     @tests.skip_if_no_agent
364)     @pytest.mark.parametrize(
365)         'config',
366)         [
367)             pytest.param(
368)                 {
369)                     'global': {'key': DUMMY_KEY1_B64},
370)                     'services': {DUMMY_SERVICE: {}},
371)                 },
372)                 id='global_config',
373)             ),
374)             pytest.param(
375)                 {'services': {DUMMY_SERVICE: {'key': DUMMY_KEY2_B64}}},
376)                 id='service_config',
377)             ),
378)             pytest.param(
379)                 {
380)                     'global': {'key': DUMMY_KEY1_B64},
381)                     'services': {DUMMY_SERVICE: {'key': DUMMY_KEY2_B64}},
382)                 },
383)                 id='full_config',
384)             ),
385)         ],
386)     )
387)     @pytest.mark.parametrize('key_index', [1, 2, 3], ids=lambda i: f'index{i}')
388)     def test_204c_key_override_on_command_line(
389)         self,
390)         monkeypatch: Any,
391)         config: dict[str, Any],
392)         key_index: int,
393)     ) -> None:
394)         def sign(
395)             _, key: bytes | bytearray, message: bytes | bytearray
396)         ) -> bytes:
397)             del message  # Unused.
398)             for value in tests.SUPPORTED_KEYS.values():
399)                 if value['public_key_data'] == key:
400)                     assert value['expected_signature'] is not None
401)                     return value['expected_signature']
402)             raise AssertionError
403) 
404)         monkeypatch.setattr(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

405)             ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys
Marco Ricci Avoid crashing when overrid...

Marco Ricci authored 1 month ago

406)         )
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

407)         monkeypatch.setattr(ssh_agent.SSHAgentClient, 'sign', sign)
Marco Ricci Avoid crashing when overrid...

Marco Ricci authored 1 month ago

408)         runner = click.testing.CliRunner(mix_stderr=False)
409)         with tests.isolated_config(
410)             monkeypatch=monkeypatch, runner=runner, config=config
411)         ):
412)             result = runner.invoke(
413)                 cli.derivepassphrase,
414)                 ['-k', DUMMY_SERVICE],
415)                 input=f'{key_index}\n'.encode('ASCII'),
416)             )
417)             assert result.stderr_bytes is not None
418)             assert (
419)                 b'Error:' not in result.stderr_bytes
420)             ), 'program exited with failure'
421)             assert result.stdout_bytes, 'program output expected'
422)             assert result.exit_code == 0, 'program exited with failure'
423) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

424)     def test_205_service_phrase_if_key_in_global_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

425)         self,
426)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

427)     ) -> None:
428)         runner = click.testing.CliRunner(mix_stderr=False)
429)         with tests.isolated_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

430)             monkeypatch=monkeypatch,
431)             runner=runner,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

432)             config={
433)                 'global': {'key': DUMMY_KEY1_B64},
434)                 'services': {
435)                     DUMMY_SERVICE: {
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

436)                         'phrase': DUMMY_PASSPHRASE.rstrip(b'\n').decode(
437)                             'ASCII'
438)                         ),
439)                         **DUMMY_CONFIG_SETTINGS,
440)                     }
441)                 },
442)             },
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

443)         ):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

444)             result = runner.invoke(
445)                 cli.derivepassphrase, [DUMMY_SERVICE], catch_exceptions=False
446)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

447)             assert result.exit_code == 0, 'program exited with failure'
448)             assert result.stdout_bytes, 'program output expected'
449)             last_line = result.stdout_bytes.splitlines(True)[-1]
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

450)             assert (
451)                 last_line.rstrip(b'\n') != DUMMY_RESULT_KEY1
452)             ), 'program generated unexpected result (key instead of phrase)'
453)             assert (
454)                 last_line.rstrip(b'\n') == DUMMY_RESULT_PASSPHRASE
455)             ), 'program generated unexpected result (wrong settings?)'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

456) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

457)     @pytest.mark.parametrize(
458)         'option',
459)         [
460)             '--lower',
461)             '--upper',
462)             '--number',
463)             '--space',
464)             '--dash',
465)             '--symbol',
466)             '--repeat',
467)             '--length',
468)         ],
469)     )
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

470)     def test_210_invalid_argument_range(
471)         self, monkeypatch: Any, option: str
472)     ) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

473)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

474)         with tests.isolated_config(
475)             monkeypatch=monkeypatch,
476)             runner=runner,
477)             config={'services': {}},
478)         ):
479)             for value in '-42', 'invalid':
480)                 result = runner.invoke(
481)                     cli.derivepassphrase,
482)                     [option, value, '-p', DUMMY_SERVICE],
483)                     input=DUMMY_PASSPHRASE,
484)                     catch_exceptions=False,
485)                 )
486)                 assert result.exit_code > 0, 'program unexpectedly succeeded'
487)                 assert (
488)                     result.stderr_bytes
489)                 ), 'program did not print any error message'
490)                 assert (
491)                     b'Error: Invalid value' in result.stderr_bytes
492)                 ), 'program did not print the expected error message'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

493) 
494)     @pytest.mark.parametrize(
495)         ['options', 'service', 'input', 'check_success'],
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

496)         [
497)             (o.options, o.needs_service, o.input, o.check_success)
498)             for o in INTERESTING_OPTION_COMBINATIONS
499)             if not o.incompatible
500)         ],
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

501)     )
502)     def test_211_service_needed(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

503)         self,
504)         monkeypatch: Any,
505)         options: list[str],
506)         service: bool | None,
507)         input: bytes | None,
508)         check_success: bool,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

509)     ) -> None:
510)         monkeypatch.setattr(cli, '_prompt_for_passphrase', tests.auto_prompt)
511)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

512)         with tests.isolated_config(
513)             monkeypatch=monkeypatch,
514)             runner=runner,
515)             config={'global': {'phrase': 'abc'}, 'services': {}},
516)         ):
517)             result = runner.invoke(
518)                 cli.derivepassphrase,
519)                 options if service else [*options, DUMMY_SERVICE],
520)                 input=input,
521)                 catch_exceptions=False,
522)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

523)             if service is not None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

524)                 assert result.exit_code > 0, 'program unexpectedly succeeded'
525)                 assert (
526)                     result.stderr_bytes
527)                 ), 'program did not print any error message'
528)                 err_msg = (
529)                     b' requires a SERVICE'
530)                     if service
531)                     else b' does not take a SERVICE argument'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

532)                 )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

533)                 assert (
534)                     err_msg in result.stderr_bytes
535)                 ), 'program did not print the expected error message'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

536)             else:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

537)                 assert (result.exit_code, result.stderr_bytes) == (
538)                     0,
539)                     b'',
540)                 ), 'program unexpectedly failed'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

541)         if check_success:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

542)             with tests.isolated_config(
543)                 monkeypatch=monkeypatch,
544)                 runner=runner,
545)                 config={'global': {'phrase': 'abc'}, 'services': {}},
546)             ):
547)                 monkeypatch.setattr(
548)                     cli, '_prompt_for_passphrase', tests.auto_prompt
549)                 )
550)                 result = runner.invoke(
551)                     cli.derivepassphrase,
552)                     [*options, DUMMY_SERVICE] if service else options,
553)                     input=input,
554)                     catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

555)                 )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

556)                 assert (result.exit_code, result.stderr_bytes) == (
557)                     0,
558)                     b'',
559)                 ), 'program unexpectedly failed'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

560) 
561)     @pytest.mark.parametrize(
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

562)         ['options', 'service'],
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

563)         [
564)             (o.options, o.needs_service)
565)             for o in INTERESTING_OPTION_COMBINATIONS
566)             if o.incompatible
567)         ],
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

568)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

569)     def test_212_incompatible_options(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

570)         self,
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

571)         monkeypatch: Any,
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

572)         options: list[str],
573)         service: bool | None,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

574)     ) -> None:
575)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

576)         with tests.isolated_config(
577)             monkeypatch=monkeypatch,
578)             runner=runner,
579)             config={'services': {}},
580)         ):
581)             result = runner.invoke(
582)                 cli.derivepassphrase,
583)                 [*options, DUMMY_SERVICE] if service else options,
584)                 input=DUMMY_PASSPHRASE,
585)                 catch_exceptions=False,
586)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

587)         assert result.exit_code > 0, 'program unexpectedly succeeded'
588)         assert result.stderr_bytes, 'program did not print any error message'
589)         assert (
590)             b'mutually exclusive with ' in result.stderr_bytes
591)         ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

592) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

593)     def test_213_import_bad_config_not_vault_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

594)         self,
595)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

596)     ) -> None:
597)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

598)         with tests.isolated_config(
599)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
600)         ):
601)             result = runner.invoke(
602)                 cli.derivepassphrase,
603)                 ['--import', '-'],
604)                 input=b'null',
605)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

606)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

607)             assert result.exit_code > 0, 'program unexpectedly succeeded'
608)             assert (
609)                 result.stderr_bytes
610)             ), 'program did not print any error message'
611)             assert (
Marco Ricci Use better error message ha...

Marco Ricci authored 1 month ago

612)                 b'Invalid vault config' in result.stderr_bytes
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

613)             ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

614) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

615)     def test_213a_import_bad_config_not_json_data(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

616)         self,
617)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

618)     ) -> None:
619)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

620)         with tests.isolated_config(
621)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
622)         ):
623)             result = runner.invoke(
624)                 cli.derivepassphrase,
625)                 ['--import', '-'],
626)                 input=b'This string is not valid JSON.',
627)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

628)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

629)             assert result.exit_code > 0, 'program unexpectedly succeeded'
630)             assert (
631)                 result.stderr_bytes
632)             ), 'program did not print any error message'
633)             assert (
634)                 b'cannot decode JSON' in result.stderr_bytes
635)             ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

636) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

637)     def test_213b_import_bad_config_not_a_file(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

638)         self,
639)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

640)     ) -> None:
641)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

642)         # `isolated_config` validates the configuration.  So, to pass an
643)         # actual broken configuration, we must open the configuration file
644)         # ourselves afterwards, inside the context.
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

645)         with tests.isolated_config(
646)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
647)         ):
648)             with open(
649)                 cli._config_filename(), 'w', encoding='UTF-8'
650)             ) as outfile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

651)                 print('This string is not valid JSON.', file=outfile)
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

652)             dname = os.path.dirname(cli._config_filename())
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

653)             result = runner.invoke(
654)                 cli.derivepassphrase,
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

655)                 ['--import', os.fsdecode(dname)],
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

656)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

657)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

658)             assert result.exit_code > 0, 'program unexpectedly succeeded'
659)             assert (
660)                 result.stderr_bytes
661)             ), 'program did not print any error message'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

662)             # Don't test the actual error message, because it is subject to
663)             # locale settings.  TODO: find a way anyway.
664) 
665)     def test_214_export_settings_no_stored_settings(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

666)         self,
667)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

668)     ) -> None:
669)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

670)         with tests.isolated_config(
671)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
672)         ):
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

673)             with contextlib.suppress(FileNotFoundError):
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

674)                 os.remove(cli._config_filename())
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

675)             result = runner.invoke(
676)                 cli.derivepassphrase, ['--export', '-'], catch_exceptions=False
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

677)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

678)             assert (result.exit_code, result.stderr_bytes) == (
679)                 0,
680)                 b'',
681)             ), 'program exited with failure'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

682) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

683)     def test_214a_export_settings_bad_stored_config(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

684)         self,
685)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

686)     ) -> None:
687)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

688)         with tests.isolated_config(
689)             monkeypatch=monkeypatch, runner=runner, config={}
690)         ):
691)             result = runner.invoke(
692)                 cli.derivepassphrase,
693)                 ['--export', '-'],
694)                 input=b'null',
695)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

696)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

697)             assert result.exit_code > 0, 'program unexpectedly succeeded'
698)             assert (
699)                 result.stderr_bytes
700)             ), 'program did not print any error message'
701)             assert (
Marco Ricci Use better error message ha...

Marco Ricci authored 1 month ago

702)                 b'Cannot load config' in result.stderr_bytes
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

703)             ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

704) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

705)     def test_214b_export_settings_not_a_file(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

706)         self,
707)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

708)     ) -> None:
709)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

710)         with tests.isolated_config(
711)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
712)         ):
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

713)             with contextlib.suppress(FileNotFoundError):
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

714)                 os.remove(cli._config_filename())
715)             os.makedirs(cli._config_filename())
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

716)             result = runner.invoke(
717)                 cli.derivepassphrase,
718)                 ['--export', '-'],
719)                 input=b'null',
720)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

721)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

722)             assert result.exit_code > 0, 'program unexpectedly succeeded'
723)             assert (
724)                 result.stderr_bytes
725)             ), 'program did not print any error message'
726)             assert (
Marco Ricci Use better error message ha...

Marco Ricci authored 1 month ago

727)                 b'Cannot load config' in result.stderr_bytes
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

728)             ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

729) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

730)     def test_214c_export_settings_target_not_a_file(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

731)         self,
732)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

733)     ) -> None:
734)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

735)         with tests.isolated_config(
736)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
737)         ):
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

738)             dname = os.path.dirname(cli._config_filename())
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

739)             result = runner.invoke(
740)                 cli.derivepassphrase,
741)                 ['--export', os.fsdecode(dname)],
742)                 input=b'null',
743)                 catch_exceptions=False,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

744)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

745)             assert result.exit_code > 0, 'program unexpectedly succeeded'
746)             assert (
747)                 result.stderr_bytes
748)             ), 'program did not print any error message'
749)             assert (
Marco Ricci Use better error message ha...

Marco Ricci authored 1 month ago

750)                 b'Cannot store config' in result.stderr_bytes
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

751)             ), 'program did not print the expected error message'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

752) 
Marco Ricci Create the configuration di...

Marco Ricci authored 1 month ago

753)     def test_214d_export_settings_settings_directory_not_a_directory(
754)         self,
755)         monkeypatch: Any,
756)     ) -> None:
757)         runner = click.testing.CliRunner(mix_stderr=False)
758)         with tests.isolated_config(
759)             monkeypatch=monkeypatch, runner=runner, config={'services': {}}
760)         ):
761)             with contextlib.suppress(FileNotFoundError):
762)                 shutil.rmtree('.derivepassphrase')
763)             with open('.derivepassphrase', 'w', encoding='UTF-8') as outfile:
764)                 print('Obstruction!!', file=outfile)
765)             result = runner.invoke(
766)                 cli.derivepassphrase,
767)                 ['--export', '-'],
768)                 input=b'null',
769)                 catch_exceptions=False,
770)             )
771)             assert result.exit_code > 0, 'program unexpectedly succeeded'
772)             assert (
773)                 result.stderr_bytes
774)             ), 'program did not print any error message'
775)             assert (
Marco Ricci Use better error message ha...

Marco Ricci authored 1 month ago

776)                 b'Cannot load config' in result.stderr_bytes
Marco Ricci Create the configuration di...

Marco Ricci authored 1 month ago

777)             ), 'program did not print the expected error message'
778) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

779)     def test_220_edit_notes_successfully(self, monkeypatch: Any) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

780)         edit_result = """
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

781) 
782) # - - - - - >8 - - - - - >8 - - - - - >8 - - - - - >8 - - - - -
783) contents go here
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

784) """
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

785)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

786)         with tests.isolated_config(
787)             monkeypatch=monkeypatch,
788)             runner=runner,
789)             config={'global': {'phrase': 'abc'}, 'services': {}},
790)         ):
791)             monkeypatch.setattr(click, 'edit', lambda *a, **kw: edit_result)  # noqa: ARG005
792)             result = runner.invoke(
793)                 cli.derivepassphrase, ['--notes', 'sv'], catch_exceptions=False
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

794)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

795)             assert (result.exit_code, result.stderr_bytes) == (
796)                 0,
797)                 b'',
798)             ), 'program exited with failure'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

799)             with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

800)                 config = json.load(infile)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

801)             assert config == {
802)                 'global': {'phrase': 'abc'},
803)                 'services': {'sv': {'notes': 'contents go here'}},
804)             }
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

805) 
806)     def test_221_edit_notes_noop(self, monkeypatch: Any) -> None:
807)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

808)         with tests.isolated_config(
809)             monkeypatch=monkeypatch,
810)             runner=runner,
811)             config={'global': {'phrase': 'abc'}, 'services': {}},
812)         ):
813)             monkeypatch.setattr(click, 'edit', lambda *a, **kw: None)  # noqa: ARG005
814)             result = runner.invoke(
815)                 cli.derivepassphrase, ['--notes', 'sv'], catch_exceptions=False
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

816)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

817)             assert (result.exit_code, result.stderr_bytes) == (
818)                 0,
819)                 b'',
820)             ), 'program exited with failure'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

821)             with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

822)                 config = json.load(infile)
823)             assert config == {'global': {'phrase': 'abc'}, 'services': {}}
824) 
825)     def test_222_edit_notes_marker_removed(self, monkeypatch: Any) -> None:
826)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

827)         with tests.isolated_config(
828)             monkeypatch=monkeypatch,
829)             runner=runner,
830)             config={'global': {'phrase': 'abc'}, 'services': {}},
831)         ):
832)             monkeypatch.setattr(click, 'edit', lambda *a, **kw: 'long\ntext')  # noqa: ARG005
833)             result = runner.invoke(
834)                 cli.derivepassphrase, ['--notes', 'sv'], catch_exceptions=False
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

835)             )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

836)             assert (result.exit_code, result.stderr_bytes) == (
837)                 0,
838)                 b'',
839)             ), 'program exited with failure'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

840)             with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

841)                 config = json.load(infile)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

842)             assert config == {
843)                 'global': {'phrase': 'abc'},
844)                 'services': {'sv': {'notes': 'long\ntext'}},
845)             }
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

846) 
847)     def test_223_edit_notes_abort(self, monkeypatch: Any) -> None:
848)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

849)         with tests.isolated_config(
850)             monkeypatch=monkeypatch,
851)             runner=runner,
852)             config={'global': {'phrase': 'abc'}, 'services': {}},
853)         ):
854)             monkeypatch.setattr(click, 'edit', lambda *a, **kw: '\n\n')  # noqa: ARG005
855)             result = runner.invoke(
856)                 cli.derivepassphrase, ['--notes', 'sv'], catch_exceptions=False
857)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

858)             assert result.exit_code != 0, 'program unexpectedly succeeded'
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

859)             assert result.stderr_bytes is not None
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

860)             assert (
861)                 b'user aborted request' in result.stderr_bytes
862)             ), 'expected error message missing'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

863)             with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

864)                 config = json.load(infile)
865)             assert config == {'global': {'phrase': 'abc'}, 'services': {}}
866) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

867)     @pytest.mark.parametrize(
868)         ['command_line', 'input', 'result_config'],
869)         [
870)             (
871)                 ['--phrase'],
872)                 b'my passphrase\n',
873)                 {'global': {'phrase': 'my passphrase'}, 'services': {}},
874)             ),
875)             (
876)                 ['--key'],
877)                 b'1\n',
878)                 {'global': {'key': DUMMY_KEY1_B64}, 'services': {}},
879)             ),
880)             (
881)                 ['--phrase', 'sv'],
882)                 b'my passphrase\n',
883)                 {
884)                     'global': {'phrase': 'abc'},
885)                     'services': {'sv': {'phrase': 'my passphrase'}},
886)                 },
887)             ),
888)             (
889)                 ['--key', 'sv'],
890)                 b'1\n',
891)                 {
892)                     'global': {'phrase': 'abc'},
893)                     'services': {'sv': {'key': DUMMY_KEY1_B64}},
894)                 },
895)             ),
896)             (
897)                 ['--key', '--length', '15', 'sv'],
898)                 b'1\n',
899)                 {
900)                     'global': {'phrase': 'abc'},
901)                     'services': {'sv': {'key': DUMMY_KEY1_B64, 'length': 15}},
902)                 },
903)             ),
904)         ],
905)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

906)     def test_224_store_config_good(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

907)         self,
908)         monkeypatch: Any,
909)         command_line: list[str],
910)         input: bytes,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

911)         result_config: Any,
912)     ) -> None:
913)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

914)         with tests.isolated_config(
915)             monkeypatch=monkeypatch,
916)             runner=runner,
917)             config={'global': {'phrase': 'abc'}, 'services': {}},
918)         ):
919)             monkeypatch.setattr(
920)                 cli, '_get_suitable_ssh_keys', tests.suitable_ssh_keys
921)             )
922)             result = runner.invoke(
923)                 cli.derivepassphrase,
924)                 ['--config', *command_line],
925)                 catch_exceptions=False,
926)                 input=input,
927)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

928)             assert result.exit_code == 0, 'program exited with failure'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

929)             with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

930)                 config = json.load(infile)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

931)             assert (
932)                 config == result_config
933)             ), 'stored config does not match expectation'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

934) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

935)     @pytest.mark.parametrize(
936)         ['command_line', 'input', 'err_text'],
937)         [
938)             (
939)                 [],
940)                 b'',
Marco Ricci Fix error message capitaliz...

Marco Ricci authored 1 month ago

941)                 b'Cannot update global settings without actual settings',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

942)             ),
943)             (
944)                 ['sv'],
945)                 b'',
Marco Ricci Fix error message capitaliz...

Marco Ricci authored 1 month ago

946)                 b'Cannot update service settings without actual settings',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

947)             ),
Marco Ricci Fix error message capitaliz...

Marco Ricci authored 1 month ago

948)             (['--phrase', 'sv'], b'', b'No passphrase given'),
949)             (['--key'], b'', b'No valid SSH key selected'),
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

950)         ],
951)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

952)     def test_225_store_config_fail(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

953)         self,
954)         monkeypatch: Any,
955)         command_line: list[str],
956)         input: bytes,
957)         err_text: bytes,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

958)     ) -> None:
959)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

960)         with tests.isolated_config(
961)             monkeypatch=monkeypatch,
962)             runner=runner,
963)             config={'global': {'phrase': 'abc'}, 'services': {}},
964)         ):
965)             monkeypatch.setattr(
966)                 cli, '_get_suitable_ssh_keys', tests.suitable_ssh_keys
967)             )
968)             result = runner.invoke(
969)                 cli.derivepassphrase,
970)                 ['--config', *command_line],
971)                 catch_exceptions=False,
972)                 input=input,
973)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

974)             assert result.exit_code != 0, 'program unexpectedly succeeded?!'
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

975)             assert result.stderr_bytes is not None
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

976)             assert (
977)                 err_text in result.stderr_bytes
978)             ), 'expected error message missing'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

979) 
980)     def test_225a_store_config_fail_manual_no_ssh_key_selection(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

981)         self,
982)         monkeypatch: Any,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

983)     ) -> None:
984)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

985)         with tests.isolated_config(
986)             monkeypatch=monkeypatch,
987)             runner=runner,
988)             config={'global': {'phrase': 'abc'}, 'services': {}},
989)         ):
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

990)             custom_error = 'custom error message'
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

991) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

992)             def raiser() -> None:
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

993)                 raise RuntimeError(custom_error)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

994) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

995)             monkeypatch.setattr(cli, '_select_ssh_key', raiser)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

996)             result = runner.invoke(
997)                 cli.derivepassphrase,
998)                 ['--key', '--config'],
999)                 catch_exceptions=False,
1000)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1001)             assert result.exit_code != 0, 'program unexpectedly succeeded'
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

1002)             assert result.stderr_bytes is not None
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1003)             assert (
1004)                 custom_error.encode() in result.stderr_bytes
1005)             ), 'expected error message missing'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1006) 
Marco Ricci Add missing tests for rewor...

Marco Ricci authored 1 month ago

1007)     def test_225b_store_config_fail_manual_no_ssh_agent(
1008)         self,
1009)         monkeypatch: Any,
1010)     ) -> None:
1011)         runner = click.testing.CliRunner(mix_stderr=False)
1012)         with tests.isolated_config(
1013)             monkeypatch=monkeypatch,
1014)             runner=runner,
1015)             config={'global': {'phrase': 'abc'}, 'services': {}},
1016)         ):
1017)             monkeypatch.delenv('SSH_AUTH_SOCK', raising=False)
1018)             result = runner.invoke(
1019)                 cli.derivepassphrase,
1020)                 ['--key', '--config'],
1021)                 catch_exceptions=False,
1022)             )
1023)             assert result.exit_code != 0, 'program unexpectedly succeeded'
1024)             assert result.stderr_bytes is not None
1025)             assert (
1026)                 b'Cannot find running SSH agent' in result.stderr_bytes
1027)             ), 'expected error message missing'
1028) 
1029)     def test_225c_store_config_fail_manual_bad_ssh_agent_connection(
1030)         self,
1031)         monkeypatch: Any,
1032)     ) -> None:
1033)         runner = click.testing.CliRunner(mix_stderr=False)
1034)         with tests.isolated_config(
1035)             monkeypatch=monkeypatch,
1036)             runner=runner,
1037)             config={'global': {'phrase': 'abc'}, 'services': {}},
1038)         ):
1039)             monkeypatch.setenv('SSH_AUTH_SOCK', os.getcwd())
1040)             result = runner.invoke(
1041)                 cli.derivepassphrase,
1042)                 ['--key', '--config'],
1043)                 catch_exceptions=False,
1044)             )
1045)             assert result.exit_code != 0, 'program unexpectedly succeeded'
1046)             assert result.stderr_bytes is not None
1047)             assert (
1048)                 b'Cannot connect to SSH agent' in result.stderr_bytes
1049)             ), 'expected error message missing'
1050) 
1051)     @pytest.mark.parametrize('try_race_free_implementation', [True, False])
1052)     def test_225d_store_config_fail_manual_read_only_file(
1053)         self,
1054)         monkeypatch: Any,
1055)         try_race_free_implementation: bool,
1056)     ) -> None:
1057)         runner = click.testing.CliRunner(mix_stderr=False)
1058)         with tests.isolated_config(
1059)             monkeypatch=monkeypatch,
1060)             runner=runner,
1061)             config={'global': {'phrase': 'abc'}, 'services': {}},
1062)         ):
1063)             tests.make_file_readonly(
1064)                 cli._config_filename(),
1065)                 try_race_free_implementation=try_race_free_implementation,
1066)             )
1067)             result = runner.invoke(
1068)                 cli.derivepassphrase,
1069)                 ['--config', '--length=15', DUMMY_SERVICE],
1070)                 catch_exceptions=False,
1071)             )
1072)             assert result.exit_code != 0, 'program unexpectedly succeeded'
1073)             assert result.stderr_bytes is not None
1074)             assert (
1075)                 b'Cannot store config' in result.stderr_bytes
1076)             ), 'expected error message missing'
1077) 
1078)     def test_225e_store_config_fail_manual_custom_error(
1079)         self,
1080)         monkeypatch: Any,
1081)     ) -> None:
1082)         runner = click.testing.CliRunner(mix_stderr=False)
1083)         with tests.isolated_config(
1084)             monkeypatch=monkeypatch,
1085)             runner=runner,
1086)             config={'global': {'phrase': 'abc'}, 'services': {}},
1087)         ):
1088)             custom_error = 'custom error message'
1089) 
1090)             def raiser(config: Any) -> None:
1091)                 del config
1092)                 raise RuntimeError(custom_error)
1093) 
1094)             monkeypatch.setattr(cli, '_save_config', raiser)
1095)             result = runner.invoke(
1096)                 cli.derivepassphrase,
1097)                 ['--config', '--length=15', DUMMY_SERVICE],
1098)                 catch_exceptions=False,
1099)             )
1100)             assert result.exit_code != 0, 'program unexpectedly succeeded'
1101)             assert result.stderr_bytes is not None
1102)             assert (
1103)                 custom_error.encode() in result.stderr_bytes
1104)             ), 'expected error message missing'
1105) 
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

1106)     def test_226_no_arguments(self, monkeypatch: Any) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1107)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

1108)         with tests.isolated_config(
1109)             monkeypatch=monkeypatch,
1110)             runner=runner,
1111)             config={'services': {}},
1112)         ):
1113)             result = runner.invoke(
1114)                 cli.derivepassphrase, [], catch_exceptions=False
1115)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

1116)         assert result.exit_code != 0, 'program unexpectedly succeeded'
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

1117)         assert result.stderr_bytes is not None
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1118)         assert (
1119)             b'SERVICE is required' in result.stderr_bytes
1120)         ), 'expected error message missing'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

1121) 
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

1122)     def test_226a_no_passphrase_or_key(self, monkeypatch: Any) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1123)         runner = click.testing.CliRunner(mix_stderr=False)
Marco Ricci Isolate tests properly and...

Marco Ricci authored 1 month ago

1124)         with tests.isolated_config(
1125)             monkeypatch=monkeypatch,
1126)             runner=runner,
1127)             config={'services': {}},
1128)         ):
1129)             result = runner.invoke(
1130)                 cli.derivepassphrase, [DUMMY_SERVICE], catch_exceptions=False
1131)             )
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

1132)         assert result.exit_code != 0, 'program unexpectedly succeeded'
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

1133)         assert result.stderr_bytes is not None
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1134)         assert (
Marco Ricci Fix error message capitaliz...

Marco Ricci authored 1 month ago

1135)             b'No passphrase or key given' in result.stderr_bytes
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1136)         ), 'expected error message missing'
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

1137) 
Marco Ricci Create the configuration di...

Marco Ricci authored 1 month ago

1138)     def test_230_config_directory_nonexistant(self, monkeypatch: Any) -> None:
1139)         """the-13th-letter/derivepassphrase#6"""
1140)         runner = click.testing.CliRunner(mix_stderr=False)
1141)         with tests.isolated_config(
1142)             monkeypatch=monkeypatch,
1143)             runner=runner,
1144)             config={'services': {}},
1145)         ):
1146)             os.remove('.derivepassphrase/settings.json')
1147)             os.rmdir('.derivepassphrase')
1148)             os_makedirs_called = False
1149)             real_os_makedirs = os.makedirs
1150) 
1151)             def makedirs(*args: Any, **kwargs: Any) -> Any:
1152)                 nonlocal os_makedirs_called
1153)                 os_makedirs_called = True
1154)                 return real_os_makedirs(*args, **kwargs)
1155) 
1156)             monkeypatch.setattr(os, 'makedirs', makedirs)
1157)             result = runner.invoke(
1158)                 cli.derivepassphrase,
1159)                 ['--config', '-p'],
1160)                 catch_exceptions=False,
1161)                 input='abc\n',
1162)             )
1163)             assert (
1164)                 result.stderr_bytes == b'Passphrase:'
1165)             ), 'program unexpectedly failed?!'
1166)             assert result.exit_code == 0, 'program unexpectedly failed?!'
1167)             assert os_makedirs_called, 'os.makedirs has not been called?!'
1168)             with open(cli._config_filename(), encoding='UTF-8') as infile:
1169)                 config_readback = json.load(infile)
1170)             assert config_readback == {
1171)                 'global': {'phrase': 'abc'},
1172)                 'services': {},
1173)             }, 'config mismatch'
1174) 
1175)     def test_230a_config_directory_not_a_file(self, monkeypatch: Any) -> None:
1176)         """the-13th-letter/derivepassphrase#6"""
1177)         runner = click.testing.CliRunner(mix_stderr=False)
1178)         with tests.isolated_config(
1179)             monkeypatch=monkeypatch,
1180)             runner=runner,
1181)             config={'services': {}},
1182)         ):
1183)             _save_config = cli._save_config
1184) 
1185)             def obstruct_config_saving(*args: Any, **kwargs: Any) -> Any:
1186)                 with contextlib.suppress(FileNotFoundError):
1187)                     shutil.rmtree('.derivepassphrase')
1188)                 with open(
1189)                     '.derivepassphrase', 'w', encoding='UTF-8'
1190)                 ) as outfile:
1191)                     print('Obstruction!!', file=outfile)
1192)                 monkeypatch.setattr(cli, '_save_config', _save_config)
1193)                 return _save_config(*args, **kwargs)
1194) 
1195)             monkeypatch.setattr(cli, '_save_config', obstruct_config_saving)
Marco Ricci Fix error bubbling in outda...

Marco Ricci authored 1 month ago

1196)             result = runner.invoke(
1197)                 cli.derivepassphrase,
1198)                 ['--config', '-p'],
1199)                 catch_exceptions=False,
1200)                 input='abc\n',
1201)             )
1202)             assert result.exit_code != 0, 'program unexpectedly succeeded?!'
Marco Ricci Add missing tests for rewor...

Marco Ricci authored 1 month ago

1203)             assert result.stderr_bytes is not None
1204)             assert (
1205)                 b'Cannot store config' in result.stderr_bytes
1206)             ), 'program unexpectedly failed?!'
1207) 
1208)     def test_230b_store_config_custom_error(self, monkeypatch: Any) -> None:
1209)         runner = click.testing.CliRunner(mix_stderr=False)
1210)         with tests.isolated_config(
1211)             monkeypatch=monkeypatch,
1212)             runner=runner,
1213)             config={'services': {}},
1214)         ):
1215)             _save_config = cli._save_config
1216) 
1217)             def obstruct_config_saving(*args: Any, **kwargs: Any) -> Any:
1218)                 with contextlib.suppress(FileNotFoundError):
1219)                     shutil.rmtree('.derivepassphrase')
1220)                 with open(
1221)                     '.derivepassphrase', 'w', encoding='UTF-8'
1222)                 ) as outfile:
1223)                     print('Obstruction!!', file=outfile)
1224)                 monkeypatch.setattr(cli, '_save_config', _save_config)
1225)                 return _save_config(*args, **kwargs)
1226) 
1227)             monkeypatch.setattr(cli, '_save_config', obstruct_config_saving)
1228)             result = runner.invoke(
1229)                 cli.derivepassphrase,
1230)                 ['--config', '-p'],
1231)                 catch_exceptions=False,
1232)                 input='abc\n',
1233)             )
1234)             assert result.exit_code != 0, 'program unexpectedly succeeded?!'
1235)             assert result.stderr_bytes is not None
Marco Ricci Fix error bubbling in outda...

Marco Ricci authored 1 month ago

1236)             assert (
1237)                 b'Cannot store config' in result.stderr_bytes
1238)             ), 'program unexpectedly failed?!'
Marco Ricci Create the configuration di...

Marco Ricci authored 1 month ago

1239) 
Marco Ricci Add finished command-line i...

Marco Ricci authored 2 months ago

1240) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1241) class TestCLIUtils:
1242)     def test_100_save_bad_config(self, monkeypatch: Any) -> None:
1243)         runner = click.testing.CliRunner()
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1244)         with (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1245)             tests.isolated_config(
1246)                 monkeypatch=monkeypatch, runner=runner, config={}
1247)             ),
1248)             pytest.raises(ValueError, match='Invalid vault config'),
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1249)         ):
1250)             cli._save_config(None)  # type: ignore
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1251) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1252)     def test_101_prompt_for_selection_multiple(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1253)         @click.command()
1254)         @click.option('--heading', default='Our menu:')
1255)         @click.argument('items', nargs=-1)
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

1256)         def driver(heading: str, items: list[str]) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1257)             # from https://montypython.fandom.com/wiki/Spam#The_menu
1258)             items = items or [
1259)                 'Egg and bacon',
1260)                 'Egg, sausage and bacon',
1261)                 'Egg and spam',
1262)                 'Egg, bacon and spam',
1263)                 'Egg, bacon, sausage and spam',
1264)                 'Spam, bacon, sausage and spam',
1265)                 'Spam, egg, spam, spam, bacon and spam',
1266)                 'Spam, spam, spam, egg and spam',
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1267)                 (
1268)                     'Spam, spam, spam, spam, spam, spam, baked beans, '
1269)                     'spam, spam, spam and spam'
1270)                 ),
1271)                 (
1272)                     'Lobster thermidor aux crevettes with a mornay sauce '
1273)                     'garnished with truffle paté, brandy '
1274)                     'and a fried egg on top and spam'
1275)                 ),
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1276)             ]
1277)             index = cli._prompt_for_selection(items, heading=heading)
1278)             click.echo('A fine choice: ', nl=False)
1279)             click.echo(items[index])
1280)             click.echo('(Note: Vikings strictly optional.)')
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1281) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1282)         runner = click.testing.CliRunner(mix_stderr=True)
1283)         result = runner.invoke(driver, [], input='9')
1284)         assert result.exit_code == 0, 'driver program failed'
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1285)         assert (
1286)             result.stdout
1287)             == """\
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1288) Our menu:
1289) [1] Egg and bacon
1290) [2] Egg, sausage and bacon
1291) [3] Egg and spam
1292) [4] Egg, bacon and spam
1293) [5] Egg, bacon, sausage and spam
1294) [6] Spam, bacon, sausage and spam
1295) [7] Spam, egg, spam, spam, bacon and spam
1296) [8] Spam, spam, spam, egg and spam
1297) [9] Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam and spam
1298) [10] Lobster thermidor aux crevettes with a mornay sauce garnished with truffle paté, brandy and a fried egg on top and spam
1299) Your selection? (1-10, leave empty to abort): 9
1300) A fine choice: Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam and spam
1301) (Note: Vikings strictly optional.)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1302) """  # noqa: E501
1303)         ), 'driver program produced unexpected output'
1304)         result = runner.invoke(
1305)             driver, ['--heading='], input='', catch_exceptions=True
1306)         )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1307)         assert result.exit_code > 0, 'driver program succeeded?!'
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1308)         assert (
1309)             result.stdout
1310)             == """\
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1311) [1] Egg and bacon
1312) [2] Egg, sausage and bacon
1313) [3] Egg and spam
1314) [4] Egg, bacon and spam
1315) [5] Egg, bacon, sausage and spam
1316) [6] Spam, bacon, sausage and spam
1317) [7] Spam, egg, spam, spam, bacon and spam
1318) [8] Spam, spam, spam, egg and spam
1319) [9] Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam and spam
1320) [10] Lobster thermidor aux crevettes with a mornay sauce garnished with truffle paté, brandy and a fried egg on top and spam
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1321) Your selection? (1-10, leave empty to abort):\x20
1322) """  # noqa: E501
1323)         ), 'driver program produced unexpected output'
1324)         assert isinstance(
1325)             result.exception, IndexError
1326)         ), 'driver program did not raise IndexError?!'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1327) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1328)     def test_102_prompt_for_selection_single(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1329)         @click.command()
1330)         @click.option('--item', default='baked beans')
1331)         @click.argument('prompt')
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

1332)         def driver(item: str, prompt: str) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1333)             try:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1334)                 cli._prompt_for_selection(
1335)                     [item], heading='', single_choice_prompt=prompt
1336)                 )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1337)             except IndexError:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1338)                 click.echo('Boo.')
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1339)                 raise
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1340)             else:
1341)                 click.echo('Great!')
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1342) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1343)         runner = click.testing.CliRunner(mix_stderr=True)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1344)         result = runner.invoke(
1345)             driver, ['Will replace with spam. Confirm, y/n?'], input='y'
1346)         )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1347)         assert result.exit_code == 0, 'driver program failed'
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1348)         assert (
1349)             result.stdout
1350)             == """\
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1351) [1] baked beans
1352) Will replace with spam. Confirm, y/n? y
1353) Great!
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1354) """
1355)         ), 'driver program produced unexpected output'
1356)         result = runner.invoke(
1357)             driver,
1358)             ['Will replace with spam, okay? ' '(Please say "y" or "n".)'],
1359)             input='',
1360)         )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1361)         assert result.exit_code > 0, 'driver program succeeded?!'
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1362)         assert (
1363)             result.stdout
1364)             == """\
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1365) [1] baked beans
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1366) Will replace with spam, okay? (Please say "y" or "n".):\x20
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1367) Boo.
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1368) """
1369)         ), 'driver program produced unexpected output'
1370)         assert isinstance(
1371)             result.exception, IndexError
1372)         ), 'driver program did not raise IndexError?!'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1373) 
1374)     def test_103_prompt_for_passphrase(self, monkeypatch: Any) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1375)         monkeypatch.setattr(
1376)             click,
1377)             'prompt',
1378)             lambda *a, **kw: json.dumps({'args': a, 'kwargs': kw}),
1379)         )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1380)         res = json.loads(cli._prompt_for_passphrase())
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1381)         err_msg = 'missing arguments to passphrase prompt'
1382)         assert 'args' in res, err_msg
1383)         assert 'kwargs' in res, err_msg
1384)         assert res['args'][:1] == ['Passphrase'], err_msg
1385)         assert res['kwargs'].get('default') == '', err_msg
1386)         assert not res['kwargs'].get('show_default', True), err_msg
1387)         assert res['kwargs'].get('err'), err_msg
1388)         assert res['kwargs'].get('hide_input'), err_msg
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1389) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1390)     @pytest.mark.parametrize(
1391)         ['command_line', 'config', 'result_config'],
1392)         [
1393)             (
1394)                 ['--delete-globals'],
1395)                 {'global': {'phrase': 'abc'}, 'services': {}},
1396)                 {'services': {}},
1397)             ),
1398)             (
1399)                 ['--delete', DUMMY_SERVICE],
1400)                 {
1401)                     'global': {'phrase': 'abc'},
1402)                     'services': {DUMMY_SERVICE: {'notes': '...'}},
1403)                 },
1404)                 {'global': {'phrase': 'abc'}, 'services': {}},
1405)             ),
1406)             (
1407)                 ['--clear'],
1408)                 {
1409)                     'global': {'phrase': 'abc'},
1410)                     'services': {DUMMY_SERVICE: {'notes': '...'}},
1411)                 },
1412)                 {'services': {}},
1413)             ),
1414)         ],
1415)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1416)     def test_203_repeated_config_deletion(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1417)         self,
1418)         monkeypatch: Any,
1419)         command_line: list[str],
Marco Ricci Consolidate `types` submodu...

Marco Ricci authored 1 month ago

1420)         config: _types.VaultConfig,
1421)         result_config: _types.VaultConfig,
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1422)     ) -> None:
1423)         runner = click.testing.CliRunner(mix_stderr=False)
1424)         for start_config in [config, result_config]:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1425)             with tests.isolated_config(
1426)                 monkeypatch=monkeypatch, runner=runner, config=start_config
1427)             ):
1428)                 result = runner.invoke(
1429)                     cli.derivepassphrase, command_line, catch_exceptions=False
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1430)                 )
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1431)                 assert (result.exit_code, result.stderr_bytes) == (
1432)                     0,
1433)                     b'',
1434)                 ), 'program exited with failure'
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1435)                 with open(cli._config_filename(), encoding='UTF-8') as infile:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1436)                     config_readback = json.load(infile)
1437)                 assert config_readback == result_config
1438) 
1439)     def test_204_phrase_from_key_manually(self) -> None:
1440)         assert (
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

1441)             dpp.vault.Vault(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1442)                 phrase=DUMMY_PHRASE_FROM_KEY1, **DUMMY_CONFIG_SETTINGS
1443)             ).generate(DUMMY_SERVICE)
1444)             == DUMMY_RESULT_KEY1
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1445)         )
1446) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1447)     @pytest.mark.parametrize(
1448)         ['vfunc', 'input'],
1449)         [
1450)             (cli._validate_occurrence_constraint, 20),
1451)             (cli._validate_length, 20),
1452)         ],
1453)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1454)     def test_210a_validate_constraints_manually(
1455)         self,
1456)         vfunc: Callable[[click.Context, click.Parameter, Any], int | None],
1457)         input: int,
1458)     ) -> None:
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1459)         ctx = cli.derivepassphrase.make_context(cli.PROG_NAME, [])
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1460)         param = cli.derivepassphrase.params[0]
1461)         assert vfunc(ctx, param, input) == input
1462) 
1463)     @tests.skip_if_no_agent
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1464)     @pytest.mark.parametrize('conn_hint', ['none', 'socket', 'client'])
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

1465)     def test_227_get_suitable_ssh_keys(
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1466)         self,
1467)         monkeypatch: Any,
1468)         conn_hint: str,
Marco Ricci Fix miscellaneous type chec...

Marco Ricci authored 2 months ago

1469)     ) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1470)         monkeypatch.setattr(
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

1471)             ssh_agent.SSHAgentClient, 'list_keys', tests.list_keys
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

1472)         )
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

1473)         hint: ssh_agent.SSHAgentClient | socket.socket | None
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1474)         match conn_hint:
1475)             case 'client':
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

1476)                 hint = ssh_agent.SSHAgentClient()
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1477)             case 'socket':
1478)                 hint = socket.socket(family=socket.AF_UNIX)
1479)                 hint.connect(os.environ['SSH_AUTH_SOCK'])
1480)             case _:
1481)                 assert conn_hint == 'none'
1482)                 hint = None
1483)         exception: Exception | None = None
1484)         try:
1485)             list(cli._get_suitable_ssh_keys(hint))
1486)         except RuntimeError:  # pragma: no cover
1487)             pass
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

1488)         except Exception as e:  # noqa: BLE001 # pragma: no cover
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1489)             exception = e
1490)         finally: