Coverage for tests\test_derivepassphrase_types.py: 100.000%

1# SPDX-FileCopyrightText: 2025 Marco Ricci <software@the13thletter.info>

2#

3# SPDX-License-Identifier: Zlib

4

5 from __future__ import annotations (empty)

6

7 import copy (empty)

8 import math (empty)

9 import types (empty)

10

11 import hypothesis (empty)

12 import pytest (empty)

13 from hypothesis import strategies (empty)

14 from typing_extensions import Any (empty)

15

16 import tests (empty)

17 from derivepassphrase import _types (empty)

18

19

20@strategies.composite (empty)

21 def js_atoms_strategy( (empty)

22 draw: strategies.DrawFn,

23) -> int | float | str | bytes | bool | None:

24 """Yield a JS atom."""

25 return draw( 1 ctx 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 )

35

36

37@strategies.composite (empty)

38 def js_nested_strategy(draw: strategies.DrawFn) -> Any: (empty)

39 """Yield an arbitrary and perhaps nested JS value."""

40 return draw( 1 ctx 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 )

68

69

70 class Parametrize(types.SimpleNamespace): (empty)

71 VALID_VAULT_TEST_CONFIGS = pytest.mark.parametrize( (empty)

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( (empty)

81 'test_config', tests.TEST_CONFIGS, ids=tests._test_config_ids

82 )

83

84

85@hypothesis.given(value=js_nested_strategy()) (empty)

86@hypothesis.example(float('nan')) 2 ctx 1ab

87 def test_100_js_truthiness(value: Any) -> None: (empty)

88 """Determine the truthiness of a value according to JavaScript.

89

90 Use hypothesis to generate test values.

91

92 """

93 expected = ( 2 ctx 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 2 ctx 1be

102

103

104@Parametrize.VALID_VAULT_TEST_CONFIGS (empty)

105 def test_200_is_vault_config(test_config: tests.VaultTestConfig) -> None: (empty)

106 """Is this vault configuration recognized as valid/invalid?

107

108 Check all test configurations that do not need custom validation

109 settings.

110

111 This primarily tests the [`_types.is_vault_config`][] and

112 [`_types.clean_up_falsy_vault_config_values`][] functions.

113

114 """

115 obj, comment, _ = test_config 1 ctx 1d

116 obj = copy.deepcopy(obj) 1 ctx 1d

117 _types.clean_up_falsy_vault_config_values(obj) 1 ctx 1d

118 assert _types.is_vault_config(obj) == (not comment), ( 1 ctx 1d

119 'failed to complain about: ' + comment

120 if comment

121 else 'failed on valid example'

122 )

123

124

125@hypothesis.given( (empty)

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)

134 def test_200a_is_vault_config_smudged( (empty)

135 test_config: tests.VaultTestConfig,

136) -> None:

137 """Is this vault configuration recognized as valid/invalid?

138

139 Generate test data via hypothesis by smudging all valid test

140 configurations.

141

142 This primarily tests the [`_types.is_vault_config`][] and

143 [`_types.clean_up_falsy_vault_config_values`][] functions.

144

145 """

146 obj_, comment, _ = test_config 1 ctx 1b

147 obj = copy.deepcopy(obj_) 1 ctx 1b

148 did_cleanup = _types.clean_up_falsy_vault_config_values(obj) 1 ctx 1b

149 assert _types.is_vault_config(obj) == (not comment), ( 1 ctx 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_), ( 1 ctx 1b

155 'mismatched report on cleanup work'

156 )

157

158

159@Parametrize.VAULT_TEST_CONFIGS (empty)

160 def test_400_validate_vault_config(test_config: tests.VaultTestConfig) -> None: (empty)

161 """Validate this vault configuration.

162

163 Check all test configurations, including those with non-standard

164 validation settings.

165

166 This primarily tests the [`_types.validate_vault_config`][] and

167 [`_types.clean_up_falsy_vault_config_values`][] functions.

168

169 """

170 obj, comment, validation_settings = test_config 1 ctx 1c

171 (allow_unknown_settings,) = validation_settings or (True,) 1 ctx 1c

172 obj = copy.deepcopy(obj) 1 ctx 1c

173 _types.clean_up_falsy_vault_config_values(obj) 1 ctx 1c

174 if comment: 1 ctx 1c

175 with pytest.raises((TypeError, ValueError)): 1 ctx 1c

176 _types.validate_vault_config( 1 ctx 1c

177 obj,

178 allow_unknown_settings=allow_unknown_settings,

179 )

180 else:

181 try: 1 ctx 1c

182 _types.validate_vault_config( 1 ctx 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

188

189

190@hypothesis.given( (empty)

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)

199 def test_400a_validate_vault_config_smudged( (empty)

200 test_config: tests.VaultTestConfig,

201) -> None:

202 """Validate this vault configuration.

203

204 Generate test data via hypothesis by smudging all smudgable test

205 configurations.

206

207 This primarily tests the [`_types.validate_vault_config`][] and

208 [`_types.clean_up_falsy_vault_config_values`][] functions.

209

210 """

211 obj_, comment, validation_settings = test_config 1 ctx 1b

212 (allow_unknown_settings,) = validation_settings or (True,) 1 ctx 1b

213 obj = copy.deepcopy(obj_) 1 ctx 1b

214 did_cleanup = _types.clean_up_falsy_vault_config_values(obj) 1 ctx 1b

215 if comment: 1 ctx 1b

216 with pytest.raises((TypeError, ValueError)): 1 ctx 1b

217 _types.validate_vault_config( 1 ctx 1b

218 obj,

219 allow_unknown_settings=allow_unknown_settings,

220 )

221 else:

222 try: 1 ctx 1b

223 _types.validate_vault_config( 1 ctx 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_), ( 1 ctx 1b

230 'mismatched report on cleanup work'

231 )