Coverage for tests\test_derivepassphrase_types.py: 100.000%
60 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-23 12:17 +0200
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-23 12:17 +0200
1# SPDX-FileCopyrightText: 2025 Marco Ricci <software@the13thletter.info>
2#
3# SPDX-License-Identifier: Zlib
5from __future__ import annotations
7import copy
8import math
9import types
11import hypothesis
12import pytest
13from hypothesis import strategies
14from typing_extensions import Any
16import tests
17from derivepassphrase import _types
20@strategies.composite
21def js_atoms_strategy(
22 draw: strategies.DrawFn,
23) -> int | float | str | bytes | bool | None:
24 """Yield a JS atom."""
25 return draw( 1b
26 strategies.one_of(
27 strategies.integers(),
28 strategies.floats(allow_nan=False, allow_infinity=False),
29 strategies.text(max_size=100),
30 strategies.binary(max_size=100),
31 strategies.booleans(),
32 strategies.none(),
33 ),
34 )
37@strategies.composite
38def js_nested_strategy(draw: strategies.DrawFn) -> Any:
39 """Yield an arbitrary and perhaps nested JS value."""
40 return draw( 1b
41 strategies.one_of(
42 js_atoms_strategy(),
43 strategies.builds(tuple),
44 strategies.builds(list),
45 strategies.builds(dict),
46 strategies.builds(set),
47 strategies.builds(frozenset),
48 strategies.recursive(
49 js_atoms_strategy(),
50 lambda s: strategies.one_of(
51 strategies.frozensets(s, max_size=100),
52 strategies.builds(
53 tuple, strategies.frozensets(s, max_size=100)
54 ),
55 ),
56 max_leaves=8,
57 ),
58 strategies.recursive(
59 js_atoms_strategy(),
60 lambda s: strategies.one_of(
61 strategies.lists(s, max_size=100),
62 strategies.dictionaries(strategies.text(max_size=100), s),
63 ),
64 max_leaves=25,
65 ),
66 ),
67 )
70class Parametrize(types.SimpleNamespace):
71 VALID_VAULT_TEST_CONFIGS = pytest.mark.parametrize(
72 'test_config',
73 [
74 conf
75 for conf in tests.TEST_CONFIGS
76 if conf.validation_settings in {None, (True,)}
77 ],
78 ids=tests._test_config_ids,
79 )
80 VAULT_TEST_CONFIGS = pytest.mark.parametrize(
81 'test_config', tests.TEST_CONFIGS, ids=tests._test_config_ids
82 )
85@hypothesis.given(value=js_nested_strategy())
86@hypothesis.example(float('nan')) 1ab
87def test_100_js_truthiness(value: Any) -> None:
88 """Determine the truthiness of a value according to JavaScript.
90 Use hypothesis to generate test values.
92 """
93 expected = ( 1be
94 value is not None # noqa: PLR1714
95 and value != False # noqa: E712
96 and value != 0
97 and value != 0.0
98 and value != ''
99 and not (isinstance(value, float) and math.isnan(value))
100 )
101 assert _types.js_truthiness(value) == expected 1be
104@Parametrize.VALID_VAULT_TEST_CONFIGS
105def test_200_is_vault_config(test_config: tests.VaultTestConfig) -> None:
106 """Is this vault configuration recognized as valid/invalid?
108 Check all test configurations that do not need custom validation
109 settings.
111 This primarily tests the [`_types.is_vault_config`][] and
112 [`_types.clean_up_falsy_vault_config_values`][] functions.
114 """
115 obj, comment, _ = test_config 1d
116 obj = copy.deepcopy(obj) 1d
117 _types.clean_up_falsy_vault_config_values(obj) 1d
118 assert _types.is_vault_config(obj) == (not comment), ( 1d
119 'failed to complain about: ' + comment
120 if comment
121 else 'failed on valid example'
122 )
125@hypothesis.given(
126 test_config=tests.smudged_vault_test_config(
127 config=strategies.sampled_from([
128 conf
129 for conf in tests.TEST_CONFIGS
130 if tests.is_valid_test_config(conf)
131 ])
132 )
133)
134def test_200a_is_vault_config_smudged(
135 test_config: tests.VaultTestConfig,
136) -> None:
137 """Is this vault configuration recognized as valid/invalid?
139 Generate test data via hypothesis by smudging all valid test
140 configurations.
142 This primarily tests the [`_types.is_vault_config`][] and
143 [`_types.clean_up_falsy_vault_config_values`][] functions.
145 """
146 obj_, comment, _ = test_config 1b
147 obj = copy.deepcopy(obj_) 1b
148 did_cleanup = _types.clean_up_falsy_vault_config_values(obj) 1b
149 assert _types.is_vault_config(obj) == (not comment), ( 1b
150 'failed to complain about: ' + comment
151 if comment
152 else 'failed on valid example'
153 )
154 assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), ( 1b
155 'mismatched report on cleanup work'
156 )
159@Parametrize.VAULT_TEST_CONFIGS
160def test_400_validate_vault_config(test_config: tests.VaultTestConfig) -> None:
161 """Validate this vault configuration.
163 Check all test configurations, including those with non-standard
164 validation settings.
166 This primarily tests the [`_types.validate_vault_config`][] and
167 [`_types.clean_up_falsy_vault_config_values`][] functions.
169 """
170 obj, comment, validation_settings = test_config 1c
171 (allow_unknown_settings,) = validation_settings or (True,) 1c
172 obj = copy.deepcopy(obj) 1c
173 _types.clean_up_falsy_vault_config_values(obj) 1c
174 if comment: 1c
175 with pytest.raises((TypeError, ValueError)): 1c
176 _types.validate_vault_config( 1c
177 obj,
178 allow_unknown_settings=allow_unknown_settings,
179 )
180 else:
181 try: 1c
182 _types.validate_vault_config( 1c
183 obj,
184 allow_unknown_settings=allow_unknown_settings,
185 )
186 except (TypeError, ValueError) as exc: # pragma: no cover
187 assert not exc, 'failed to validate valid example' # noqa: PT017
190@hypothesis.given(
191 test_config=tests.smudged_vault_test_config(
192 config=strategies.sampled_from([
193 conf
194 for conf in tests.TEST_CONFIGS
195 if tests.is_smudgable_vault_test_config(conf)
196 ])
197 )
198)
199def test_400a_validate_vault_config_smudged(
200 test_config: tests.VaultTestConfig,
201) -> None:
202 """Validate this vault configuration.
204 Generate test data via hypothesis by smudging all smudgable test
205 configurations.
207 This primarily tests the [`_types.validate_vault_config`][] and
208 [`_types.clean_up_falsy_vault_config_values`][] functions.
210 """
211 obj_, comment, validation_settings = test_config 1b
212 (allow_unknown_settings,) = validation_settings or (True,) 1b
213 obj = copy.deepcopy(obj_) 1b
214 did_cleanup = _types.clean_up_falsy_vault_config_values(obj) 1b
215 if comment: 1b
216 with pytest.raises((TypeError, ValueError)): 1b
217 _types.validate_vault_config( 1b
218 obj,
219 allow_unknown_settings=allow_unknown_settings,
220 )
221 else:
222 try: 1b
223 _types.validate_vault_config( 1b
224 obj,
225 allow_unknown_settings=allow_unknown_settings,
226 )
227 except (TypeError, ValueError) as exc: # pragma: no cover
228 assert not exc, 'failed to validate valid example' # noqa: PT017
229 assert did_cleanup is None or bool(did_cleanup) == (obj != obj_), ( 1b
230 'mismatched report on cleanup work'
231 )